You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将两个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:34:54