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


状态编程思想的理论知识可以参考之前写的一篇文章(  ),本文介绍一个例子--串口接收.状态机的状态定义如下:

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

 

相关内容

    暂无相关文章