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

长平狐 发布于 2013/06/03 14:52
阅读 120
收藏 0

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

状态编程思想的理论知识可以参考之前写的一篇博客(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\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;
	}
}

原文链接:http://blog.csdn.net/ce123/article/details/8864647
加载中
返回顶部
顶部