字节流数据解析

时间:2022-08-18 04:02:11

各种与硬件底层相关的数据大都是字节型的传输方式,如串口,如果协议定的不好,解析写不好,就会发生丢包。近期在做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就非常麻烦。