狀態編程思想的理論知識可以參考之前寫的一篇文章( 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\n",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\n",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\n",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;
}
}