基于状态机编程思想的串口接收程序
2019-04-15 14:18发布
生成海报
基于状态机编程思想的串口接收程序 状态编程思想的理论知识可以参考之前写的一篇博客(http://blog.csdn.net/ce123/article/details/8222673),本文介绍一个例子--串口接收.状态机的状态定义如下:typedef enum
{
IS_NULL = 0,
IS_START, //已接收到起始符号,准备接收长度
IS_LEN, //已经接收到长度,准备接收数据
IS_DATA, //已经接收到长度,准备或正在接收数据
IS_CHECK //已经接收到数据,准备计算校验和
}st_InState;
其他的定义如下:#define CHAR_STX 0xAA
#define INFRAME_MAXLEN 40
typedef struct tagINPARSE
{
u8 uInState; //接收状态,初始化为IS_NULL
u16 tInState; //接收状态计时
u8 uTotal; //需要接收数据的总长度
u8 uLen; //实际已经接收到的长度
u8 uframe_a[INFRAME_MAXLEN]; //接收到的数据帧
void* vpUserData;
}t_INPARSE;
接下来是程序的主要部分,也就是状态的转换过程./*******************************************************************************
* Function Name : FinishInScan
* Description : Finish Receive char
* Input : The pointer of t_INPARSE
* Output : None
* Return : None
*******************************************************************************/
void FinishInScan(t_INPARSE *pPtc)
{
pPtc->uInState = IS_NULL;
pPtc->uTotal = 0;
pPtc->tInState = 0;
}
/*******************************************************************************
* Function Name : InChecksum
* Description : Calculate the checksum
* Input : The pointer of t_INPARSE
* Output : None
* Return : The checksum
*******************************************************************************/
u8 InChecksum(t_INPARSE *pPtc)
{
u8 uCheck;
u16 i;
u8* ptr;
//uCheck = CHAR_STX ^ HIBYTE(pPtc->uTotal) ^ LOBYTE(pPtc->uTotal);
uCheck = CHAR_STX ^ pPtc->uTotal;
ptr = (u8*)(pPtc->uframe_a);
for (i = pPtc->uTotal; i ; --i,++ptr)
uCheck ^= *ptr;
return uCheck;
}
/*******************************************************************************
* Function Name : OnRevChar
* Description : Protocol analysis of the character stream
* Input : The pointer of t_INPARSE, Character data from COMx, User data
* Output : None
* Return : Ptc_R_
*******************************************************************************/
u8 OnRevChar(t_INPARSE *pPtc,u8 ch,void *vpUserData)
{
switch (pPtc->uInState)
{
case IS_NULL:
if (ch == 0xaa)
{
pPtc->uInState = IS_START;
//pPtc->tInState =
return Ptc_R_CONTINUE;
}
else
{
printf("Hand error,0x%x
",ch);
return Ptc_R_FALSE;
}
case IS_START: //已经接收到起始字符,准备接收长度
if ((ch <=INFRAME_MAXLEN) && (ch >= 1) )
{
pPtc->uTotal = ch;
pPtc->uLen = 0;
pPtc->uInState = IS_DATA;
return Ptc_R_CONTINUE;
}
else
{
printf("Hand error,0x%x
",ch);
return Ptc_R_FALSE;
}
case IS_DATA:
pPtc->uframe_a[pPtc->uLen++] = ch;
if (pPtc->uLen == pPtc->uTotal)
{
pPtc->uframe_a[pPtc->uLen] = 0;//添加一个串结束符
pPtc->uInState = IS_CHECK;
}
return Ptc_R_CONTINUE;
default:
u8 uCheck = InChecksum(pPtc);
if (uCheck == ch)
{
return Ptc_R_FRAME;
}
else
{
printf("Handset Frame CheckReeor.Rev = 0x%x,Calc = 0x%x
",ch,uCheck);
return Ptc_R_FALSE;
}
break;
}
}
/*******************************************************************************
* Function Name : Rev_PutChar
* Description : Character process
* Input : The pointer of t_INPARSE, Character data from COMx, User data
* Output : None
* Return : Ptc_R_
*******************************************************************************/
u8 Rev_PutChar(t_INPARSE *pPtc,u8 ch,void *vpUserData)
{
u8 rtn = OnRevChar(pPtc,ch,vpUserData);
if (rtn == Ptc_R_CONTINUE)
{
return Ptc_R_FALSE;
}
else if (rtn == Ptc_R_FALSE)
{
FinishInScan(pPtc);
return rtn;
}
else
{
FinishInScan(pPtc);
return Ptc_R_FRAME;
}
}
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮