【问题标题】:Understand Modbus RTU CRC了解 Modbus RTU CRC
【发布时间】:2021-04-20 09:26:52
【问题描述】:

现在我研究Modbus RTU和Modbus RTU的CRC16。

关于校验CRC的源码,在High-Order Byte Table和Low-Order Byte Table中,不知道这个值是怎么产生的?在 Modbus 协议的文档中,对此进行了解释:“一个数组包含 16 位 CRC 字段的高字节的所有 256 个可能的 CRC 值,另一个数组包含低字节的所有值。”

我想怎么取这个值?帮帮我,非常感谢。

Low-Order Byte Table
High-Order Byte Table

【问题讨论】:

  • 文档:Modbus_over_serial_line_V1_02.pdf,第 43/44 页
  • 使用auchCRCLo[0] 访问该数组中的第一个元素;或auchCRCHi[1] 访问该数组中的第二个元素。 ...
  • 你能解释更多吗?这些数组的值取自???
  • 显然它们是恒定的......有人计算了值(我不知道如何)并以源形式预先填充了数组。

标签: c crc modbus


【解决方案1】:

该 pdf 文件中包含 CRC 的面向位实现的描述,但它可能需要进行一些清理:

1. Load a 16–bit register with FFFF hex (all 1’s). Call this the CRC register.

2. Exclusive OR the first 8–bit byte of the message with the low–order byte
   of the 16–bit CRC register, putting the result in the CRC register.

3. Save the LSB for step 4. Shift the CRC register one bit to the right 
   (toward the LSB), zero–filling the MSB.

4. (If the saved LSB is 0): Continue to step 5.
   (If the saved LSB is 1): Exclusive OR the CRC register with the polynomial
   value 0xA001 (1010 0000 0000 0001).

5. Repeat Steps 3 and 4 until 8 shifts have been performed.
   When this is done, a complete 8–bit byte will have been processed.

6. Repeat Steps 2 through 5 for the next 8–bit byte of the message.
   Continue doing this until all bytes have been processed.

7. The final content of the CRC register is the CRC value.

8. When the CRC is placed into the message, store the low order byte first, and the
   high order byte next.   (msg ... , crclo, crchi).

https://modbus.org/docs/Modbus_over_serial_line_V1_02.pdf

请注意,在使用表格的示例代码中,CRC 的字节被交换,所以所谓的“低字节”实际上是“高字节”,反之亦然。这样做是为了允许 CRC 在大端处理器上作为 16 位值存储在消息中。在小端处理器上不需要交换字节,例如 PC 上的 X86,因为小端存储将交换字节(存储低字节,高字节)。

生成表格的示例代码:

#include <stdio.h>

typedef unsigned char    uint8_t;
typedef unsigned short  uint16_t;

uint8_t crclo[256];
uint8_t crchi[256];

    void gentbls(void)
    {
    uint16_t crc;
    uint16_t b;
    uint16_t c;
    uint16_t i;
        for(c = 0; c < 0x100; c++){
            crc = c;
            for(i = 0; i < 8; i++){
                b = crc & 1;
                crc >>= 1;
                if(b != 0) crc ^= 0xa001;
            }
            crchi[c] = crc & 0xff;
            crclo[c] = crc >> 8;
        }
    }

int main()
{
int i, j;
    gentbls();
    for(j = 0; j < 17; j++){
        for(i = 0; i < 15; i++)
            printf("%02x ", crclo[j*15+i]);
        printf("\n");
    }
    printf("%02x\n\n", crclo[255]);
    for(j = 0; j < 17; j++){
        for(i = 0; i < 15; i++)
            printf("%02x ", crchi[j*15+i]);
        printf("\n");
    }
    printf("%02x\n", crchi[255]);
    return 0;
}

输出:

00 c0 c1 01 c3 03 02 c2 c6 06 07 c7 05 c5 c4 
04 cc 0c 0d cd 0f cf ce 0e 0a ca cb 0b c9 09 
08 c8 d8 18 19 d9 1b db da 1a 1e de df 1f dd 
1d 1c dc 14 d4 d5 15 d7 17 16 d6 d2 12 13 d3 
11 d1 d0 10 f0 30 31 f1 33 f3 f2 32 36 f6 f7 
37 f5 35 34 f4 3c fc fd 3d ff 3f 3e fe fa 3a 
3b fb 39 f9 f8 38 28 e8 e9 29 eb 2b 2a ea ee 
2e 2f ef 2d ed ec 2c e4 24 25 e5 27 e7 e6 26 
22 e2 e3 23 e1 21 20 e0 a0 60 61 a1 63 a3 a2 
62 66 a6 a7 67 a5 65 64 a4 6c ac ad 6d af 6f 
6e ae aa 6a 6b ab 69 a9 a8 68 78 b8 b9 79 bb 
7b 7a ba be 7e 7f bf 7d bd bc 7c b4 74 75 b5 
77 b7 b6 76 72 b2 b3 73 b1 71 70 b0 50 90 91 
51 93 53 52 92 96 56 57 97 55 95 94 54 9c 5c 
5d 9d 5f 9f 9e 5e 5a 9a 9b 5b 99 59 58 98 88 
48 49 89 4b 8b 8a 4a 4e 8e 8f 4f 8d 4d 4c 8c 
44 84 85 45 87 47 46 86 82 42 43 83 41 81 80 
40

00 c1 81 40 01 c0 80 41 01 c0 80 41 00 c1 81 
40 01 c0 80 41 00 c1 81 40 00 c1 81 40 01 c0 
80 41 01 c0 80 41 00 c1 81 40 00 c1 81 40 01 
c0 80 41 00 c1 81 40 01 c0 80 41 01 c0 80 41 
00 c1 81 40 01 c0 80 41 00 c1 81 40 00 c1 81 
40 01 c0 80 41 00 c1 81 40 01 c0 80 41 01 c0 
80 41 00 c1 81 40 00 c1 81 40 01 c0 80 41 01 
c0 80 41 00 c1 81 40 01 c0 80 41 00 c1 81 40 
00 c1 81 40 01 c0 80 41 01 c0 80 41 00 c1 81 
40 00 c1 81 40 01 c0 80 41 00 c1 81 40 01 c0 
80 41 01 c0 80 41 00 c1 81 40 00 c1 81 40 01 
c0 80 41 01 c0 80 41 00 c1 81 40 01 c0 80 41 
00 c1 81 40 00 c1 81 40 01 c0 80 41 00 c1 81 
40 01 c0 80 41 01 c0 80 41 00 c1 81 40 01 c0 
80 41 00 c1 81 40 00 c1 81 40 01 c0 80 41 01 
c0 80 41 00 c1 81 40 00 c1 81 40 01 c0 80 41 
00 c1 81 40 01 c0 80 41 01 c0 80 41 00 c1 81 
40

【讨论】:

  • 哇非常感谢,非常清晰易懂
猜你喜欢
  • 2014-03-06
  • 2016-12-30
  • 1970-01-01
  • 2022-01-10
  • 2019-06-17
  • 2022-08-16
  • 2021-08-03
  • 1970-01-01
  • 2021-08-01
相关资源
最近更新 更多