如何将两个C结构体打包写入AT45 DataFlash并完成解包?
嘿,你尝试的嵌套结构体思路其实完全没问题,只是可能没摸透具体的操作步骤~ 下面我给你三种实用的方法,帮你搞定两个结构体的打包存储和解包读取:
方法一:嵌套结构体(最直观易维护)
这就是你尝试的思路,核心是把两个结构体打包成一个新的结构体,然后像操作单个结构体一样读写Flash,非常省心。
步骤示例:
首先定义你的原始结构体和嵌套结构体:
// 原始结构体1 typedef struct { int id; char device_name[16]; } struct_name1; // 原始结构体2 typedef struct { float temperature; uint8_t status_flag; } struct_name2; // 组合两个结构体的新结构体 typedef struct { struct_name1 a; struct_name2 b; } CombinedStruct;
打包写入Flash:
// 初始化两个结构体数据 struct_name1 my_dev = {0x001, "sensor_01"}; struct_name2 my_data = {25.6f, 0x01}; // 把数据存入组合结构体 CombinedStruct pack_data; pack_data.a = my_dev; pack_data.b = my_data; // 整体写入Flash,和单个结构体操作完全一致 flash_write(&write_addr, (uint8_t*)&pack_data, sizeof(CombinedStruct));
解包读取:
CombinedStruct unpack_data; // 读取整个组合结构体 flash_read(&read_addr, (uint8_t*)&unpack_data, sizeof(CombinedStruct)); // 取出两个原始结构体的数据 struct_name1 read_dev = unpack_data.a; struct_name2 read_data = unpack_data.b;
⚠️ 注意:编译器可能会给结构体成员之间加填充字节来保证对齐,所以sizeof(CombinedStruct)不一定等于sizeof(struct_name1)+sizeof(struct_name2)。如果需要紧凑存储(比如节省Flash空间),可以给结构体加编译器指令,比如GCC下用__attribute__((packed)):
typedef struct __attribute__((packed)) { struct_name1 a; struct_name2 b; } CombinedStruct;
但要注意,打包后的结构体可能会影响访问效率,且跨编译器/平台兼容性会降低。
方法二:连续地址读写(无需定义新结构体)
如果不想新增结构体,可以直接把两个结构体连续写入Flash,读取时按顺序读取即可,需要自己管理地址偏移。
打包写入:
struct_name1 my_dev = {0x001, "sensor_01"}; struct_name2 my_data = {25.6f, 0x01}; // 先写入第一个结构体 flash_write(&write_addr, (uint8_t*)&my_dev, sizeof(struct_name1)); // 更新地址,写入第二个结构体(注意AT45的地址单位是字节还是页,这里按字节处理) write_addr += sizeof(struct_name1); flash_write(&write_addr, (uint8_t*)&my_data, sizeof(struct_name2));
解包读取:
struct_name1 read_dev; struct_name2 read_data; // 先读取第一个结构体 flash_read(&read_addr, (uint8_t*)&read_dev, sizeof(struct_name1)); // 更新地址,读取第二个结构体 read_addr += sizeof(struct_name1); flash_read(&read_addr, (uint8_t*)&read_data, sizeof(struct_name2));
这种方式的好处是灵活,不需要额外定义结构体,但要注意地址计算不能出错,避免覆盖或读错区域。
方法三:缓冲区暂存(适合需要预处理的场景)
如果需要对数据做加密、校验等预处理,可以先把两个结构体拷贝到一块连续的缓冲区,再整体写入Flash。
打包写入:
struct_name1 my_dev = {0x001, "sensor_01"}; struct_name2 my_data = {25.6f, 0x01}; // 计算总大小,分配缓冲区(静态数组或动态分配都可以) uint8_t buffer[sizeof(struct_name1) + sizeof(struct_name2)]; // 把两个结构体拷贝到缓冲区 memcpy(buffer, &my_dev, sizeof(struct_name1)); memcpy(buffer + sizeof(struct_name1), &my_data, sizeof(struct_name2)); // (可选)在这里对buffer做预处理,比如加校验和、加密等 // ... // 整体写入Flash flash_write(&write_addr, buffer, sizeof(buffer));
解包读取:
uint8_t read_buffer[sizeof(struct_name1) + sizeof(struct_name2)]; struct_name1 read_dev; struct_name2 read_data; // 读取整个缓冲区 flash_read(&read_addr, read_buffer, sizeof(read_buffer)); // (可选)预处理逆操作,比如校验、解密等 // ... // 从缓冲区取出两个结构体 memcpy(&read_dev, read_buffer, sizeof(struct_name1)); memcpy(&read_data, read_buffer + sizeof(struct_name1), sizeof(struct_name2));
内容的提问来源于stack exchange,提问作者clamentjohn
相关产品推荐
相关产品推荐

