提问人:Rasmus Palk 提问时间:11/17/2023 更新时间:11/17/2023 访问量:70
计算UART传输的CRC:LSB还是MSB?
Calculating CRC for UART transmission LSB or MSB?
问:
我必须通过 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 和 Register 是常量,大部分摆弄发生在其余位置。Pwm A 和 B 可以是 0-255,目录 A 和 B 可以是 0 或 1。
一旦我摆弄完数据,我想计算 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;
}
我从电机驱动器的数据表(https://www.mouser.ee/datasheet/2/609/TMC7300_datasheet_rev1_08-3364772.pdf)中获得了该功能。
我的解决方案可能还有更多问题,但我认为我的问题是计算 CRC。我尝试将数据从 LSB 切换到 MSB 进行计算,但没有奏效。有什么建议吗?
答:
首先是一些细节:
字节序通常是指字节顺序。
示例:使用 BIG endian 和 2 字节时,最高有效字节存储在最低地址中,后跟最低有效字节存储在下一个较高地址中。LITTLE endian 正好相反。OP 的代码没有多字节数据,因此此问题不适用。int16_t
对于串行数据传输,也有一个字节顺序或字节序。使用 BIG endian 时,首先传输最高有效字节,然后是最低有效字节。OP 的代码没有多字节数据,因此此问题不直接适用。
在串行传输中,还有位字节序,哪个位先发送,最高有效位还是最少?通常,程序员看不到此顺序。UART 首先发送最低有效位。
OP 使用从最低寻址到最高寻址字节的结构字节。在算法中,字节从最低有效位到最高有效位使用。CalcCRC()
如果串行传输首先发送最低寻址字节,则 OP 会匹配该字节。如果串行传输首先发送最高寻址字节,则 OP 应更改为按该顺序计算 CRC。CalcCRC()
CalcCRC()
为什么CRC计算要与传输顺序匹配?
OP 在 所指向的数据中存在所有字节后计算 CRC。更高性能的代码可以在发送/接收每个字节后计算 CRC。因此,订单必须匹配。CalcCRC()
datagram
在硬件级别,一些 CRC 计算一次完成 1 位,因此传输不仅必须匹配字节顺序,还必须匹配位顺序。这通常不适用于 UART 串行传输。
鉴于 OP 和 UART 发送,我希望正确的计算顺序是大多数寻址字节的最低值。这并不意味着 BIG 或 LITTLE 端多字节类型,因为这是一个单独的问题。CalcCRC()
当然,重要的是发送方和接收方同意。
评论
您的同步字节似乎不正确。链接的文档将其显示为 .请注意位编号:0b00000101
评论
sync
slave_address