上一节我们简单的介绍了一种定长通讯协议编写,这种协议有其优点,就是实现方法简单。因为只要接收到一个包头,只需节后到n个字节即可判断一帧数据接收完成。但是这种协议的缺点很明显,就是不能容纳太多的数据。所以这一节我来讨论一个变长协议的编写。
  报文格式:68 len 功能码 数据0 数据1 数据n......校验 16,
  根据这个报文格式,我们来分析一下怎样判断一帧数据是否接收完成。可以根据以下以下几个判据来判断。
 1,首先收到的第一字节个的数据必须是0x68,如果是0X68那么表明一帧接收开始。否则则认为接收到一个错误数据。抛弃该数据。
 2,接收第二个字节,验证条件必须是len<max_rxbuf-2. 否则则认为接收的数据错误。因为如果len="">MAX_RXBUF-2会使接收的缓冲区溢出。造成系统错误,甚至系统崩溃。
  3,是否接收到len个数据?如果是检查校验位是否正确,否则接收该数据。并且检查该数据是否是0X16,判断数据正确性。如果正确置接收数据成功标志。一帧数据接收完成。
 串口接收数据结构如下:
  #define MAX_RXBUF 100   //接收缓冲区长度
 #define MAX_TXBUF  100   //发送缓冲区长度
 #define REC_FRAME     1  //一帧数据接收完成
 #define NO_REC_FRAME  0 //没有数据接收完成
  typedef struct  UART
  {
    unsigned char RX_buf[MAX_RXBUF];
   unsigned char TX_buf[MAX_TXBUF];
   unsigned char flag;    //数据接收完成标志
   unsigned char RX_count;
}
 有了以上数据结构我们来编写一下接收数据函数流程图:

 如果编写该函数代码如下:
UART  UART0={{0},{0},NO_REC_FRAME,0}   
void recive_dat(unsigned char dat)
{
  if(UART0.RX_count==0)
  {
    if(dat==0x68)
    {
      UART0.RX_count=1;
      UART0.RX_buf[0] =0x68;
     }
    return;
  }
  if(UART0.RX_count==1)
   {
     if(dat>MAX_RXBUF-2)
     {
         UART0.RX_count=0;
     }
     else
    {
        UART0.RX_count=2;
        UART0.RX_buf[1] =0xdat;
    }
    
     return;
   }
   if(UART0.RX_buf[1]==UART0.RX_count-2)
  {
     if(dat==0x16)
    {
       UART0.RX_buf[UART0.RX_count] =0x16 ;
       UART0.flag = REC_FRAME ;    
    }
    else
    {
      UART0.flag =NO_ REC_FRAME ; 
     }
  }
 else
 {
       UART0.RX_buf[UART0.RX_count] =dat ;
      UART0.RX_count++ ; 
 }
}
主函数:
 void main( )
 {
  //初始化函数
 ------
 -----
 while(1)
 {
    if(UART0.flag= =REC_FRAME )
   {
      exe_uart(  );                   //处理串口数据函数
      UART0.flag= =NO_REC_FRAME;
      UART0.RX_count=0;
  }
 }
}
  当接收到一个完整帧数据后UART0.RX_count赋值为REC_FRAME,主函数判断UART0.flag= =REC_FRAME条件成立后便会调用  exe_uart(  ) 处理接收到的数据。出具处理完成后 UART0.flag置NO_REC_FRAME, UART0.RX_count清零。可以开始接收下一帧数据了。
    这一节我们介绍了不定长数据帧的接收,其实就是怎样判断一帧数据是否接收完成。