各种与硬件底层相关的数据大都是字节型的传输方式,如串口,如果协议定的不好,解析写不好,就会发生丢包。近期在做linux串口的数据通讯时,发生了让人头疼的丢包,后分析解析代码发现一旦数据段中含有帧头便会解析不到数据,通过一上午的调试,写了一个新的解析。
#include <stdio.h>
//帧头 长度 命令 数据 校验 (帧尾:可以不需要,也可以当做简单的校验)
//解析思路:接收到帧头后,根据长度来读取数据,最后校验(如果数据中有帧头则会跳过,不影响解析)
//示例:帧头-0xaa,0x02 长度-0x07 帧尾-0xbb
uint8_t buff[24] ={0x21,0xAA,0xAA,0x02,0x07,0xAA,0xBB,0xBB,0xff,0x34,0x99,0xbb,
0xaa,0xAA,0x02,0x07,0xA7,0xB7,0xaa,0xff,0x14,0xa9,0xbb,0x00
};
int main(int argc, char *argv[])
{
uint8_t i=0;
uint8_t tbuf = 0;
uint8_t cnt = 0;//解析状态标记
uint8_t scnt = 0;//数据段角标
uint8_t slen = 0;//数据段长度
uint8_t *psbuf = NULL;//数据段缓冲区
while(i<24)
{
//printf("%x ",buff[i]);
tbuf = buff[i];
if((tbuf == 0xAA)&&(cnt == 0))//可能第一个头
cnt = 1;
switch(cnt)
{
case 1:
if(tbuf == 0x02)//第二个头
cnt = 2;
break;
case 2:
slen = tbuf;//读取长度
psbuf = (uint8_t*)malloc(slen*sizeof(uint8_t));//开辟空间
scnt = 0;//复位数据段缓冲区
cnt = 3;
printf("slen:%d\n",slen);
break;
case 3:
psbuf[scnt] = tbuf;
if(scnt == slen-1)
{
cnt = 0;//接收到最后一个字节就复位
printf("finished!\n");//解析完毕
for(int k=0;k<slen;k++)
printf("%x ",psbuf[k]);
printf("\n");
free(psbuf);//释放动态内存
}
scnt++;
break;
default:
break;
}
i++;
}
printf("\n");
return 0;
}
- 调试经验:在qt中不要强行想把协议和串口类分开,因为实现起来比较困难,虽然可以利用回调和继承实现但是如果用到ui,需要在回调和继承里更新ui就非常麻烦。