基于状态机编程思想的串口接收程序

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; } }