计算UART传输的CRC LSB或MSB?

问题描述 投票:0回答:1

我必须通过 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进行计算,但没有成功。有什么建议吗?

c uart crc
1个回答
0
投票

首先一些细节:

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 多字节类型,因为这是一个单独的问题。

当然重要的是发送者和接收者都同意。

© www.soinside.com 2019 - 2024. All rights reserved.