我必须通过 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,dir 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进行计算,但没有成功。有什么建议吗?
首先一些细节:
Endian 通常指的是 byte 顺序。
示例:对于 BIG endian 和 2 字节
int16_t
,最高有效字节存储在最低地址中,然后最低有效字节存储在下一个较高地址中。 LITTLE endian 则相反。 OP的代码没有多字节数据,所以这个问题不适用。
对于串行数据传输,也有字节顺序或字节序。对于 BIG endian,首先传输最高有效字节,然后是最低有效字节。 OP的代码没有多字节数据,所以这个问题不直接适用。
在串行传输中,也有位字节序(bit endian),即哪一位先发送,最高有效位还是最低有效位?通常程序员看不到这个顺序。 UART 首先发送最低有效位。
OP 的
CalcCRC()
使用最低地址到最高地址的字节。在算法中,字节按从最低有效位到最高有效位的顺序使用。
如果串行传输首先发送最低地址字节,则 OP 的
CalcCRC()
与之匹配。如果串行传输首先发送最高寻址字节,则 OP 的 CalcCRC()
应更改为按该顺序计算 CRC。
为什么CRC计算要与传输顺序匹配?
OP 的
CalcCRC()
在所有字节都出现在 datagram
指向的数据中后计算 CRC。更高性能的代码可以在发送/接收每个字节后计算 CRC。因此订单必须匹配。
在硬件层面,一些CRC计算是一次1位完成的,因此传输不仅必须匹配字节顺序,还必须匹配位顺序。
考虑到 OP 的
CalcCRC()
并通过 UART 发送,我预计正确的计算顺序是最低寻址字节到大多数。这并不意味着 BIG 或 LITTLE 多字节类型,因为这是一个单独的问题。
当然重要的是发送者和接收者都同意。