首页 / 操作系统 / Linux / 基于状态机编程思想的串口接收程序
状态编程思想的理论知识可以参考之前写的一篇文章( http://www.linuxidc.com/Linux/2013-04/83616.htm ),本文介绍一个例子--串口接收.状态机的状态定义如下:typedef enum
{
IS_NULL = 0,
IS_START, //已接收到起始符号,准备接收长度
IS_LEN, //已经接收到长度,准备接收数据
IS_DATA, //已经接收到长度,准备或正在接收数据
IS_CHECK //已经接收到数据,准备计算校验和
}st_InState;其他的定义如下:/*******************************************************************************
* 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;
}
}