UART传输CRC计算:基于LSB原始数据还是MSB传输数据?
CRC计算的字节格式疑问与代码问题
需通过UART传输8字节数据,最后一字节为CRC。已掌握CRC计算方法,但不确定应基于LSB格式的原始数据,还是UART传输时的MSB格式数据进行计算。当前采用紧凑结构体划分1字节数据块,代码如下:
typedef struct __attribute__((packed)){ uint8_t sync; uint8_t slave_address; uint8_t register_address; uint8_t pwmA; uint8_t dirA; uint8_t pwmB; uint8_t dirB; uint8_t crc; } packet_t; packet_t new_sig = { .sync = 0b10100000, .slave_address = 0b10000000, .register_address = 0b01000101, .pwmA = 0b0, .dirA = 0b0, .pwmB = 0b0, .dirB = 0b0, .crc = 0b0, };
所有数据均为LSB格式,sync、slave_address、register_address为常量,pwmA/B取值0-255,dirA/B为0或1。使用从TMC7300 datasheet获取的CalcCRC函数计算CRC:
void CalcCRC(unsigned char* datagram, unsigned char datagramLength) { int i,j; unsigned char* crc = datagram + (datagramLength-1); // CRC located in last byte of message unsigned char currentByte; *crc = 0; for (i=0; i<(datagramLength-1); i++) { // Execute for all bytes of a message currentByte = datagram[i]; // Retrieve a byte to be sent from Array for (j=0; j<8; j++) { if ((*crc >> 7) ^ (currentByte&0x01)) // update CRC based result of XOR operation { *crc = (*crc << 1) ^ 0x07; } else { *crc = (*crc << 1); } currentByte = currentByte >> 1; } // for CRC bit } // for message byte new_sig.crc = *crc; }
已尝试将数据从LSB转换为MSB进行计算但未解决问题,以下是针对性建议:
- 优先参考TMC7300手册的CRC示例:直接查手册中的CRC计算样例,用已知的输入数据包和对应正确CRC值做对比测试——这是最快定位问题的方法。比如找手册给出的「输入数据包+正确CRC」组合,用你的代码计算,看结果是否匹配。
- 修复CalcCRC的冗余赋值:函数最后一行
new_sig.crc = *crc;完全多余,因为crc指针已经指向datagram的最后一字节(即new_sig.crc),直接通过*crc赋值即可。保留这行可能导致传入其他datagram时出现错误,建议删除。 - 校验位处理顺序:当前CalcCRC是按字节的LSB到MSB顺序处理每一位(通过
currentByte&0x01取最低位,再右移字节)。如果TMC7300要求按字节MSB到LSB顺序计算CRC,需修改位处理逻辑:- 将
currentByte&0x01改为(currentByte >> 7) & 0x01(取最高位) - 将
currentByte = currentByte >> 1改为currentByte = currentByte << 1(左移取次高位)
- 将
- UART传输顺序不影响字节级CRC计算:UART的MSB/LSB传输是字节内部的位顺序,只要收发两端的CRC计算都基于相同的字节数值(即结构体中存储的原始值),就不需要因为UART传输顺序修改CRC计算的字节数据——除非接收端会先反转每个字节的位再计算CRC,这种情况才需要提前反转字节后再算CRC。
- 确认结构体内存布局:
__attribute__((packed))已确保结构体按定义顺序紧凑排列,无字节对齐问题,这部分无需调整。
内容的提问来源于stack exchange,提问作者Rasmus Palk
相关产品推荐
相关产品推荐

