串口通信实际包含了物理层、数据链路层、应用层三方面的功能。这里的解包和打包指的是在应用层的操作,因为应用数据是在这一层由开发人员自行编写的;
如果应用数据采用的纯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;
}
三、混合方式的,可灵活采用上述两种方式;