如何将UDT_HEAD结构体数据打包为数组?相关技术疑问
/** * @brief 将逻辑UDT_HEAD打包为10个数据字节(80比特),PDU格式遵循ETSI标准。 * * 重要提示:在打包80比特UDT_HEAD数据前,需调用bw_init重置10字节输出缓冲区。 * * @param in UDT结构体指针 * @param data 输出用的10字节缓冲区 * * @return 0:成功写入恰好80比特 * @return -1:输入指针为NULL * @return -2:DPF标识非UDT类型 * @return -3:比特写入溢出 * @return -4:最终比特位置不等于80 */ static int udt_head_pack_data(const udt_head_t *in, uint8_t data[UDT_HEAD_DATA_OCTETS]) { (void)in; (void)data; return -99; }
技术问询
- 如何在
udt_head_pack_data函数中完成将udt_head_t结构体的数据打包到目标uint8_t数组的操作? - 存在一个用于打包32位数据的函数,但UDT_HEAD头部并无32位相关字段,该如何适配该函数的相关条件?
问题解答
1. 实现UDT_HEAD结构体到字节数组的打包逻辑
核心是严格遵循ETSI标准定义的UDT_HEAD位格式,通过位操作逐字段写入目标数组,步骤如下:
- 参数合法性校验:先检查
in和data是否为NULL,是则返回-1;再校验in中的DPF字段是否为UDT标识,不符合则返回-2。 - 初始化位写入环境:按照注释要求调用
bw_init重置输出缓冲区,该函数通常会维护当前写入的比特偏移量。 - 逐字段写入比特流:根据ETSI标准中每个字段的起始位、长度、端序要求,用位掩码、移位操作将结构体字段值依次填充到
data的对应位置。比如某字段占6位,就从当前比特偏移开始,将字段值按大端/小端规则写入对应字节的指定比特位。 - 结果校验:写完所有字段后,检查最终比特偏移是否刚好为80,否则返回-4;若过程中写入超过80比特则返回-3;全部正常则返回0。
示例核心代码片段(假设bw_put_bits是写入指定比特数的辅助函数):
static int udt_head_pack_data(const udt_head_t *in, uint8_t data[UDT_HEAD_DATA_OCTETS]) { if (!in || !data) return -1; if (in->dpf != DPF_TYPE_UDT) return -2; bw_init(data, UDT_HEAD_DATA_OCTETS); // 按ETSI标准依次写入各字段,示例字段长度仅为演示 if (bw_put_bits(in->reserved, 3) != 0) return -3; if (bw_put_bits(in->message_type, 5) != 0) return -3; if (bw_put_bits(in->sequence_num, 16) != 0) return -3; // ... 继续写入剩余字段,总比特数累计为80 if (bw_get_current_bitpos() != 80) return -4; return 0; }
2. 适配32位打包函数到非32位字段
可以通过以下两种方式适配现有32位打包函数:
- 字段拼接凑整:将连续的多个小字段拼接成一个32位临时值,再调用32位打包函数写入。比如两个16位字段可以合并为一个32位值,或者多个零散小字段(如3位+5位+24位)凑成32位后一次性写入。
- 单字段包装适配:对于单个小于32位的字段,先将其值填充到32位变量的对应位置(根据端序左移或右移补零),调用32位打包函数时指定仅写入该字段的实际比特长度。如果原32位打包函数不支持指定写入长度,就手动调整比特偏移量,跳过未使用的冗余比特。
示例适配代码(假设pack_32bit是现有32位打包函数):
// 包装函数:将小字段适配为32位格式后调用打包函数 static int pack_small_field(uint16_t field_val, int bit_len, uint8_t *buf) { // 按大端规则将小字段值移到32位变量的高位 uint32_t tmp_val = (uint32_t)field_val << (32 - bit_len); // 调用32位打包函数,指定仅写入bit_len长度的比特 return pack_32bit(tmp_val, buf, bit_len); } // 在udt_head_pack_data中调用适配函数 if (pack_small_field(in->priority, 4, data) != 0) return -3;
内容的提问来源于stack exchange,提问作者Gopinath R K
相关产品推荐
相关产品推荐

