关于上一篇自定义协议的命令解析器,解决了很大一部分问题,但是并不完整, 代码可读性还是较差。因为对于字节所表示的含义真是太原始了,需要的是变量所表示的含义。幸好我多看了几篇文章,找到了个解决方法。同时这个解决方法能顺便把协议的报文打包问题给解决了。报文解析和打包就像是硬币的正反面一样是不可分割的。
大致实现思路
参考的两篇文章是:“结构体嵌入联合体”在协议解析中的神操作,认识认识#pragma、#error指令一个提供大致的实现思路,一个解决实际操作中遇到的内存对齐问题。那篇文章并没有解决字节数据可读性的问题,所以只能说提供了大致的实现思路。那篇文章是这样的:
我使用的方式是这样的,将字节数组提取出来,放在联合体中,每个结构体只表示需要的变量的含义。
调用方式是这样的:
/* 由字节数组方式 转为 结构体方式查看 */
sPack * data_pack = (sPack *)RecvBuff;
/* 输出 接收缓冲区中表示 参数长度 的字节 */
printf("data_pack param_length is : %d \r\n", data_pack->param_length);
/* 输出 接收缓冲区中表示 方法 的字节 */
printf("data_pack method is : %d \r\n", data_pack->method);
/* 输出 接收缓冲区其余字节数据 */
for(uint8_t i=0; i<MAX_LENGTH - 2; i++)
{
printf("0x%02x ", *(data_pack->data.data + i));
}
printf("\n\n");
/* 调用相应的函数对数据进行解析 */
test_func1(&(data_pack->data));
test_func2(&(data_pack->data));
test_func3(&(data_pack->data));
test_func4(&(data_pack->data));
void test_func1(DataField * user_data)
{
if(user_data == NULL) //if(! user_data)
{
return;
}
printf("from function : %s \r\n", __FUNCTION__);
/* 调用数据:可读、可写 */
printf("steer address is : 0x%04x \r\n", user_data->func_type1.steer_addr);
printf("steer angle is : 0x%04x \r\n", user_data->func_type1.steer_angle);
printf("motor address is : 0x%04x \r\n", user_data->func_type1.motor_addr);
printf("motor speed is : 0x%02x \r\n", user_data->func_type1.motor_speed);
}
遇到的问题
在实际测试的过程中,遇到一个字节对齐的问题,现象就不描述了,有感兴趣的可以将以下两句话注销掉。前后对比一下。
#pragma pack(1) /* 指定按1字节对齐 */
#pragma pack() /* 取消自定义字节对齐 */
验证结果
源代码
以下源代码是可以直接编译运行的,运行方式不大清楚的可以查看这篇文章:编译C代码环境搭建,推荐使用VS Code,如果嫌麻烦的话也可以网上搜菜鸟C在线工具,直接复制过去点击运行。
#include <stdio.h>
#include <stdint.h>
#define MAX_LENGTH 15
#pragma pack(1) /* 指定按1字节对齐 */