蒙蒙plus
蒙蒙plus
发布于 2024-04-26 / 51 阅读
0
0

字节对齐与协议解析

字节对齐与报文解析

#pragma pack(show) //显示当前内存对齐的字节数,编辑器默认8字节对齐

#pragma pack(n) //设置编辑器按照n个字节对齐,n可以取值1,2,4,8,16

#pragma pack(push) //将当前的对齐字节数压入栈顶,不改变对齐字节数

#pragma pack(push,n) //将当前的对齐字节数压入栈顶,并按照n字节对齐

#pragma pack(pop) //弹出栈顶对齐字节数,不改变对齐字节数

#pragma pack(pop,n) //弹出栈顶并直接丢弃,按照n字节对齐

前言

擅长用字节对齐可以节省脑细胞,提高代码可读性,这里为大家展示下配置字节对齐来高效的解析报文。

示例场景

如下报文格式

字节 类型 功能 说明
CMD 0x10
SCMD 0x10
2
1
1
4
1
4
[4]
U16
U8
U8
Float
U8
Float
[Float]
Type
Chnnl
State
Value
Num
AD1
[AD2]
数据 1 的测量状态和测量值:
Type:表示数据类型,详见附录 B。
Chnnl:表示数据通道
State:表示数据状态
b7:数值有效/无效:1-有效,0-无效
b6~b3:为 0,预留
b2~b0:数值单位,详见附录 B。
Value:表示数据测量值
Num:电参量个数
AD1:对应实测电参量 1
AD2:对应实测电参量 2
…:对应实测点参量 n
[2]
[1]
[1]
[4]
[1]
[4]
[4]
[U16]
[U8]
[U8]
[Float]
[U8]
[Float]
[Float] …
Type
Chnnl
State
Value
Num
AD1
[AD2]
数据 2 的测量状态和测量值:
数据 n 的测量状态和测量值:

对应报文可以如下设计

#pragma pack(1)
typedef struct _PROTOCOL_0X1010
{
    uint16_t type;
    uint8_t chnnl;
    uint8_t state;
    float value;
    uint8_t num;
    float AD[0];
} protocol_0x1010_t;

#pragma pack()

关键信息解释:

  1. #pragma pack(1)#pragma pack() 是成对出现的,否则将影响后续其它结构体的对齐问题,这里进行1字节对齐,牺牲了MCU的效率换来的是可读取,而牺牲的效率我认为比我们手动操作强的多。
  2. AD[0] 柔性数组,在结构体中可以方便对后续数据的读取工作,AD多个参数便可之间访问,避免类型转换问题。

使用示例

        uint32_t i = 0;
        while (i <= pfrm->length)
        {
            protocol_0x1010_ptr data_ptr = (protocol_0x1010_ptr) & (pfrm->text[i]);
            uint8_t sensor_idx = sensor_info_find_idx(data_ptr->type);
            if (sensor_idx < DEV_MAX_ID)
            {
                sensor_value_t *sensor_value_ptr = &m_sensor_module.value[sensor_idx];
                sensor_value_ptr->status.online = (data_ptr->state & 0x80) != 0;
                sensor_value_ptr->tick = tick_cur;
                sensor_value_ptr->meas = data_ptr->value;
                sensor_value_ptr->raw = data_ptr->AD[0];
                i += sizeof(protocol_0x1010_t) + data_ptr->num * sizeof(float);
            }

        }

评论