1. Modbus CRC16 算法规范
Modbus 使用的 CRC 算法标准称为'Modbus CRC-16'或'CRC-16-IBM',也叫 CRC-16-ANSI,多项式为:
多项式 = x^16 + x^15 + x^2 + 1
用 16 进制表示时,多项式是 0x8005(但注意,Modbus 是高位在前运算,这里 Modbus 采用的是位逆序后的 0xA001 进行右移计算)。
算法初始值和结果异或: 初始 CRC 值 = 0xFFFF
实际上,在 Modbus RTU 中,计算时每个字节先与 CRC 低字节异或,然后 CRC 右移 1 位,如果移出位是 1 则与多项式 0xA001 异或(这是 0x8005 的位逆序多项式)。计算完所有字节后,得到的 CRC 值在传输时是低字节在前(Little-endian 字节顺序)附加在帧末尾。
简单概括: 取当前数据的 1 位,与 CRC 的低位(bit 0)异或,结果记为 xorBit,然后 CRC 右移 1 位,如果 xorBit 为 0,继续取数据的下一位;如果 xorBit 为 1,则 CRC 与多项式 0xA001 异或。
2. 对 01 03 00 00 00 01 进行 CRC 计算
使用上述算法进行计算。
字节 0x01: crc = 0xFFFF ^ 0x01 = 0xFFFE (1111 1111 1111 1110) 循环 8 次(一次一位):
- 位 0:crc & 1 = 0 → 右移 1 位:0x7FFF
- 位 1:0x7FFF & 1 = 1 → 右移 1 位得 0x3FFF,然后异或 0xA001:0x3FFF ^ 0xA001 = 0x9FFE
- 位 2:0x9FFE & 1 = 0 → 0x4FFF
- 位 3:0x4FFF & 1 = 1 → 右移:0x27FF ^ 0xA001 = 0x87FE
- 位 4:0x87FE & 1 = 0 → 0x43FF
- 位 5:0x43FF & 1 = 1 → 右移:0x21FF ^ 0xA001 = 0x81FE
- 位 6:0x81FE & 1 = 0 → 0x40FF
- 位 7:0x40FF & 1 = 1 → 右移:0x207F ^ 0xA001 = 0x807E 处理完字节 0x01 后,CRC = 0x807E。
字节 0x03: crc ^= 0x03 → 0x807E ^ 0x03 = 0x807D 循环 8 次:
- 0x807D & 1 = 1 → 右移:0x403E ^ 0xA001 = 0xE03F
- 0xE03F & 1 = 1 → 右移:0x701F ^ 0xA001 = 0xD01E
- 0xD01E & 1 = 0 → 0x680F
- 0x680F & 1 = 1 → 右移:0x3407 ^ 0xA001 = 0x9406
- 0x9406 & 1 = 0 → 0x4A03
- 0x4A03 & 1 = 1 → 右移:0x2501 ^ 0xA001 = 0x8500
- 0x8500 & 1 = 0 → 0x4280
- 0x4280 & 1 = 0 → 0x2140 CRC = 0x2140
字节 0x00:(跟 0 异或结果是本身) crc ^= 0x00 = 0x2140 循环 8 次(每次 crc & 1 都是 0,因为 0x2140 二进制 0010 0001 0100 0000,最低位是 0,但右移过程中最低位会变化,我们仔细算):
- 0x2140 & 1 = 0 → 0x10A0
- 0x10A0 & 1 = 0 → 0x0850
- 0x0850 & 1 = 0 → 0x0428
- 0x0428 & 1 = 0 → 0x0214
- 0x0214 & 1 = 0 → 0x010A
- 0x010A & 1 = 0 → 0x0085
- 0x0085 & 1 = 1 → 右移:0x0042 ^ 0xA001 = 0xA043
- 0xA043 & 1 = 1 → 右移:0x5021 ^ 0xA001 = 0xF020 CRC = 0xF020
字节 0x00: crc ^= 0x00 = 0xF020 循环:
- 0xF020 & 1 = 0 → 0x7810
- 0x7810 & 1 = 0 → 0x3C08
- 0x3C08 & 1 = 0 → 0x1E04
- 0x1E04 & 1 = 0 → 0x0F02



