MODBUS CRC16 校验码在线计算与报文解析(RTU、ASCII、TCP)
粘贴任意十六进制格式的 MODBUS 报文,立即就能看到校验码是否正确、每个字节的含义以及寄存器里的数值。计算器会自动识别 MODBUS RTU、ASCII 和 TCP,按两种字节顺序校验 RTU 的 CRC,校验 ASCII 的 LRC,并为没有校验码的数据补上校验码。它在您的浏览器中运行,不会把任何数据发送出去。
MODBUS 报文或数据
计算器如何识别报文
每一行都会按各种 MODBUS 格式依次尝试,第一个结构成立的格式胜出:
| 格式 | 识别方法 | 校验方式 |
|---|---|---|
| MODBUS TCP | 第 3、4 字节为 00 00(协议标识符),第 5、6 字节给出后面的字节数 | 无:由 MBAP 报文头代替 |
| MODBUS ASCII | 行以冒号开头且只包含十六进制字符,可以是文本,也可以是 3A 30 31 ... 这样的字节 | LRC,最后一个字节 |
| MODBUS RTU | 最后两个字节是前面各字节的 CRC,低字节在前或高低字节颠倒 | CRC-16,最后两个字节 |
| 没有校验码的数据 | 以上都不是,而长度符合不带校验码的请求或响应 | 计算器给出需要追加的 CRC 和 LRC |
请求还是响应,由长度判断。读寄存器的请求总是 6 个字节加校验码;响应则带有字节数。如果功能码 01 到 04 的响应紧跟在其请求的下一行,计算器会用寄存器编号(40001 ...)命名各寄存器,并检查数量是否一致。03 和 04 响应中的寄存器值可按各种类型显示:32 位和 64 位浮点数与整数、文本以及 BCD 日期和时间都会自动识别,适用于任何字节序和字序。
MODBUS CRC 的计算方法
MODBUS RTU 使用 CRC-16/MODBUS:多项式 0x8005 的反射形式(0xA001),初值 0xFFFF,没有最终异或。CRC 覆盖从从站地址到最后一个数据字节的全部字节,发送时低字节在前。对于请求 01 03 00 00 00 0A,CRC 为 0xCDC5,因此完整的帧是 01 03 00 00 00 0A C5 CD。
uint16_t modbus_crc(const uint8_t *buf, size_t len)
{
uint16_t crc = 0xFFFF;
for (size_t i = 0; i < len; i++) {
crc ^= buf[i];
for (int b = 0; b < 8; b++)
crc = (crc & 1) ? (crc >> 1) ^ 0xA001 : crc >> 1;
}
return crc; /* 先发送 crc & 0xFF,再发送 crc >> 8 */
}
def modbus_crc(data: bytes) -> int:
crc = 0xFFFF
for b in data:
crc ^= b
for _ in range(8):
crc = (crc >> 1) ^ 0xA001 if crc & 1 else crc >> 1
return crc # 01 03 00 00 00 0A -> 0xCDC5,发送为 C5 CD
少数设备把两个 CRC 字节反过来发送,高字节在前。这不是标准 MODBUS,但帧本身没有问题;计算器会标记为 CRC 高低字节颠倒,与这类设备通信的软件必须接受这种顺序。MODBUS 测试工具(英文)也能发送 CRC 颠倒的请求。
MODBUS ASCII:LRC
MODBUS ASCII 帧是文本:一个冒号,每个字节写成两个十六进制字符,LRC 再占两个字符,最后是 CR LF。LRC 是冒号和 LRC 之间各字节(不是字符)8 位累加和的二进制补码。对于 01 03 00 00 00 0A,和为 0x0E,所以 LRC 为 F2,整个帧写作 :01030000000AF2,后跟 CR LF。
MODBUS TCP:没有校验码
MODBUS TCP 帧不带 CRC,数据由 TCP 保护。它以 7 字节的 MBAP 报文头开始:响应会重复的事务标识符、协议标识符 0、后面的字节数,以及单元标识符(网关用它作为其后面设备的从站地址)。上面的请求通过 TCP 发送时是 00 01 00 00 00 06 01 03 00 00 00 0A。对每一帧,计算器还会给出其 RTU、ASCII 和 TCP 形式,可以直接复制。
CRC 不对时
| 原因 | 迹象 |
|---|---|
| 线路干扰 | 错误时有时无;电缆较长、没有终端电阻、没有共地 |
| 端口设置与设备接近但不相同 | 大部分应答失败;校验位或波特率不对会让每个字节都出错 |
| 两台设备使用相同的从站地址 | 应答在总线上冲突 |
| 报文复制不完整 | 缺少或重复了某个字节;请用长度和字节数对照 |
| 非标准设备 | CRC 数值正确但高低字节颠倒:计算器会明确提示 |
更多原因请看串口乱码和常见 COM 口错误页面。
输入格式
十六进制字节可以用空格、逗号、分号、短横线或冒号分隔,也可以不加分隔符:01 03 00 0A、0103000A、01-03-00-0A。支持 0x01、#01、$01、\x01 和 01h 这样的前缀和后缀,也支持 {0x01, 0x03, 0x00, 0x0A} 这样的 C 数组。MODBUS ASCII 帧可以直接以文本粘贴,末尾带不带 CR LF 都可以。每行一帧,最多读取 20 行,因此可以把请求和它的响应一起粘贴进来。粘贴按钮一键把剪贴板中的文本放进输入框;第一次使用时浏览器可能会请求权限。
测试设备或捕获通信数据
计算器处理的是您已有的报文。要从设备获取报文:
- 从浏览器向设备发送请求,逐字节查看每个应答:在线 MODBUS 测试工具(英文)。要先找到从站地址,请使用 MODBUS 扫描工具(英文)。
- 监视主站与设备之间的通信,充当主站或从站,实时解析报文:Advanced Serial Port Monitor 及其 MODBUS 插件(英文)。
- 全天候轮询设备,把数值记录到文件、Excel 或数据库:Advanced Serial Data Logger(英文)及其 MODBUS 插件(英文)。
常见问题
MODBUS CRC 是怎样计算的?
MODBUS RTU 使用 CRC-16/MODBUS:初值为 0xFFFF,把每个字节异或到低字节,然后右移 8 次,每次移出的位为 1 时与 0xA001 异或。结果低字节在前附加到帧尾。对于 01 03 00 00 00 0A,CRC 为 0xCDC5,发送为 C5 CD。
MODBUS RTU 的 CRC 哪个字节在前?
低字节在前。少数设备高字节在前发送;本计算器能识别这种颠倒的顺序并给出提示。
MODBUS TCP 使用 CRC 吗?
不使用。MODBUS TCP 帧以 7 字节的 MBAP 报文头开始(事务标识符、协议标识符 0、长度、单元标识符),没有校验码,因为 TCP 本身会保护数据。
MODBUS ASCII 的 LRC 是怎样计算的?
把冒号和 LRC 之间的所有字节(从站地址、功能码和数据,按字节而不是按字符)相加,保留低 8 位,再取二进制补码。对于 01 03 00 00 00 0A,和为 0x0E,LRC 为 F2。
为什么我的报文 CRC 对不上?
有字节在传输中被改变(线路干扰、缺少共地或终端电阻),端口设置与设备接近但不相同,两台设备同时应答(RS485 总线冲突),或者报文复制不完整。如果计算器提示 CRC 高低字节颠倒,说明设备使用非标准的字节顺序。
计算器会把我的数据发送到别处吗?
不会。所有计算都在您的浏览器中完成。页面只记录使用了哪些按钮,用于匿名的总体使用统计,不包含报文内容。