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
相关产品推荐
相关产品推荐

