串口数据的打包和解包


串口通信实际包含了物理层、数据链路层、应用层三方面的功能。这里的解包和打包指的是在应用层的操作,因为应用数据是在这一层由开发人员自行编写的;
如果应用数据采用的纯ASCII方式传输的,主要好处就是人为可识别,但报文会相应加长;采用纯Hex字节方式传输的,同样的数据量下报文较短,但是不好识别,字符显示看起来就像乱码。也有混合在一起,报文的部分字段用ASCII定义,部分字段采用Hex字节方式的,这里不表。


一、像纯ASCII方式的,一般用字符串格式命令,比如sprintf,sscanf等;比如报文是以固定的“$AAA,”开头并带固定格式的,就可采用下述方式的解析:

struct MS_AAA
{
   char flag;
   float PDOP;
   float HDOP;
   float VDOP;

   int analyze(const char* ch)
   {
       int crc = 0;
       if ( 0 < sscanf (ch, "$AAA,%c,%f,%f,%f*%d\r\n", //这里就是报文的格式
                               &flag,
                               &PDOP,
                               &HDOP,
                               &VDOP,
                               &crc))
        {

            //这里其实可以看看校验crc到底对不对
            return 0;
        }
        return -1;
   }
};

二、像纯Hex字节方式传输的,一般会采用一个结构体来描述报文(注意字节对齐),然后通过结构体指针和字符指针之间的强制转型的方式进行,比如报文起始就是16进制表示的4字节ID号、2字节报文长度、4字节时戳的,就可如下的解析:

#pragma pack(1)  //单字节对齐
typedef struct
{
     uint32_t id;
     uint16_t lenth;
     uint32_t timestamp;
} FrameHeader;

int handleRecvData(const unsigned char* uch)
{
    int i = 0;
    FrameHeader header = *((FrameHeader*)&uch[0]);
    if (header.id != 0x35)
    {
           printf("#### frame's ID error.\n");
           return -1;
    }
    if (header.lenth > 1400)
    {
           printf("#### frame's Lenth error.\n");
           return -2;
    }
     //****
     return 0;
}

三、混合方式的,可灵活采用上述两种方式;

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM