上一节我们简单的介绍了一种定长通讯协议编写,这种协议有其优点,就是实现方法简单。因为只要接收到一个包头,只需节后到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清零。可以开始接收下一帧数据了。
这一节我们介绍了不定长数据帧的接收,其实就是怎样判断一帧数据是否接收完成。