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

TI C2000无uint8_t时,如何让句柄按字节访问结构体数据?

解决C2000无uint8_t支持下的SPI字节传输结构体问题

问题根源

C2000架构仅支持16位指针/数据类型,无法直接使用uint8_t。当你用uint16_t*直接指向结构体并按字节传输时,编译器会把单个字节的访问转换为16位操作(高字节补0),导致原uint32_t数据被错误拆分为0x00XX形式的16位单元,最终写入EEPROM后数据异常。

解决方案

方案1:直接拆分/拼接16位字(推荐)

利用C2000的16位内存访问特性,将结构体转为uint16_t数组,拆分每个16位字的高低字节进行SPI传输,接收时再拼接回16位字。

修改后代码:

typedef struct
{
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
} MCL_Struct_t;

MCL_Struct_t struc_write = {0};
MCL_Struct_t struc_read = {0};
// 将结构体转为uint16_t数组,长度为结构体字节数/2
uint16_t *struc_write_words = (uint16_t *)&struc_write;
uint16_t *struc_read_words = (uint16_t *)&struc_read;
const uint16_t STRUCT_WORD_CNT = sizeof(MCL_Struct_t) / sizeof(uint16_t);

// 初始化结构体数据
struc_write.a = 0x11112222;
struc_write.b = 0x11113333;
struc_write.c = 0x11114444;
struc_write.d = 0x11115555;

// 写入EEPROM:拆分每个16位字为两个字节发送
for(uint16_t i = 0; i < STRUCT_WORD_CNT; i++)
{
    uint16_t curr_word = struc_write_words[i];
    // 发送低字节(SPI仅传输低8位,高字节补0不影响)
    EEPROM_sendByte((uint16_t)(curr_word & 0x00FF));
    // 发送高字节
    EEPROM_sendByte((uint16_t)((curr_word >> 8) & 0x00FF));
}

// 从EEPROM读取:拼接两个字节为一个16位字
for(uint16_t i = 0; i < STRUCT_WORD_CNT; i++)
{
    uint16_t byte_low = EEPROM_receiveByte();
    uint16_t byte_high = EEPROM_receiveByte();
    struc_read_words[i] = (uint16_t)((byte_high << 8) | byte_low);
}

方案2:临时缓冲区中转

如果无法修改SPI底层发送/接收函数,可提前将结构体字节打包为uint16_t数组(每个元素存单个字节),传输完成后再拼接回结构体:

typedef struct
{
    uint32_t a;
    uint32_t b;
    uint32_t c;
    uint32_t d;
} MCL_Struct_t;

MCL_Struct_t struc_write = {0};
MCL_Struct_t struc_read = {0};
const uint16_t STRUCT_BYTE_CNT = sizeof(MCL_Struct_t);
const uint16_t STRUCT_WORD_CNT = STRUCT_BYTE_CNT / sizeof(uint16_t);
// 临时缓冲区:每个元素存一个字节(高字节补0)
uint16_t write_buf[STRUCT_BYTE_CNT];
uint16_t read_buf[STRUCT_BYTE_CNT];

// 初始化结构体
struc_write.a = 0x11112222;
struc_write.b = 0x11113333;
struc_write.c = 0x11114444;
struc_write.d = 0x11115555;

// 结构体转临时缓冲区
uint16_t *src_words = (uint16_t *)&struc_write;
for(uint16_t i = 0; i < STRUCT_WORD_CNT; i++)
{
    uint16_t curr_word = src_words[i];
    write_buf[2*i] = (uint16_t)(curr_word & 0x00FF);
    write_buf[2*i + 1] = (uint16_t)((curr_word >> 8) & 0x00FF);
}

// 写入EEPROM
EEPROM_writeTransaction(eepromAddr, write_buf, STRUCT_BYTE_CNT);

// 读取EEPROM
EEPROM_readTransaction(eepromAddr, STRUCT_BYTE_CNT);
memcpy(read_buf, SPI_DMA_Handle.pSPIRXDMA->pbuffer, STRUCT_BYTE_CNT);

// 临时缓冲区转结构体
uint16_t *dst_words = (uint16_t *)&struc_read;
for(uint16_t i = 0; i < STRUCT_WORD_CNT; i++)
{
    uint16_t byte_low = read_buf[2*i];
    uint16_t byte_high = read_buf[2*i + 1];
    dst_words[i] = (uint16_t)((byte_high << 8) | byte_low);
}

注意事项

  • 字节序一致性:C2000为小端架构,拆分/拼接时需保证字节顺序与EEPROM存储逻辑一致,避免数据反转。
  • 内存对齐:MCL_Struct_t的uint32_t成员在C2000上自然对齐,转为uint16_t*访问无对齐问题。
  • 禁止直接字节指针访问:C2000编译器会将uint8_t*的访问转换为16位操作,导致高字节补0,这正是你遇到数据异常的核心原因。

内容的提问来源于stack exchange,提问作者HansPeterLoft

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 06:07:07