串口校验速查(CRC / 累加和 Sum / 异或 XOR)
依据 Modbus 公开规范与常见串口约定整理。校验位本身不修复数据,只用于接收方判断帧是否被破坏。
从一条”发出去却石沉大海”的指令说起
调试一台带私有 HEX 协议的中控设备,你照着手册把开机指令一字节不差敲进串口调试助手,回车——设备毫无反应。你开始怀疑波特率、怀疑接线、怀疑设备坏了,折腾半小时,最后发现是末尾那两个校验字节的高低位发反了。设备收到帧后一算校验对不上,认定这帧被破坏,直接静默丢弃,连个错误码都不给。这就是校验类故障最阴的地方:它不报错,只是”没反应”,把你往完全错误的方向带。这篇把展厅最常遇到的三种校验——异或 XOR、累加和 Sum、CRC-16/Modbus——讲清楚,给你能拿计算器逐字节验算的实例。
校验是什么、为什么要
串口(RS232/RS485)在长线、强干扰环境下,某一位电平可能被翻转,0x30 传着传着变成 0x31。接收方光看字节没法判断这是不是原始数据。于是协议在每帧末尾附一段校验值:发送方按约定算法算出校验、附在帧尾一起发;接收方收到后用同样算法把数据段重算一遍,比对末尾的校验值一致才认这帧有效,不一致就丢弃。
记住一个前提:校验只”发现”错误,不”改正”错误。 它不是纠错码,接收方一旦发现对不上,唯一动作就是丢弃整帧。展厅里 Modbus 设备、私有 HEX 协议的报文大多带校验,所以校验算错 = 设备直接丢弃指令、毫无响应,且不报错,现象和”没接线""波特率错”几乎一样,病根却完全不同。
速查:三种常见校验
| 校验 | 长度 | 算法概述 | 典型用途 | 字节序 |
|---|---|---|---|---|
| CRC-16/Modbus | 2 字节 | 多项式 0xA001,初值 0xFFFF | Modbus RTU | 低字节在前 |
| 累加和 Sum | 1~2 字节 | 数据字节算术相加,取低 8/16 位 | 大量私有协议 | 视协议 |
| 异或 XOR (LRC 类) | 1 字节 | 所有数据字节逐个异或 | 简单私有协议 | 单字节无序 |
| LRC(Modbus ASCII) | 1 字节 | 字节求和取负(二进制补码) | Modbus ASCII | 单字节 |
三者抗错能力递增:XOR 最弱(两位同时翻转可能互相抵消、校验照过),Sum 略好,CRC 最强。但你不能自己挑——校验方式是设备定死的,你的任务是搞清它用哪种、算对它。
CRC-16/Modbus 字节序坑:算出 16 位 CRC 后,RTU 帧里先发低字节、再发高字节。很多人把高低字节发反,设备就一直无响应——这是新手最高频的翻车点,没有之一。
三种校验的手算示例(可自己验算)
下面每个例子你都能拿计算器或纸笔跟着走一遍。这三个值都经过实算核对,你算出来对不上就是哪一步错了,回头查。
异或 XOR:最简单
把校验范围内所有字节逐个做按位异或(相同为 0、不同为 1)。异或满足交换律,字节顺序不影响结果。
例,数据 01 03 00 00:
0x01 ^ 0x03 = 0x02
0x02 ^ 0x00 = 0x02
0x02 ^ 0x00 = 0x02 → 校验 = 0x02,帧尾补 02
再换个数据 01 03 00 0A:0x01 ^ 0x03 = 0x02,0x02 ^ 0x00 = 0x02,0x02 ^ 0x0A = 0x08 → 校验 08。
累加和 Sum:直接相加
把范围内所有字节算术相加,按协议取低 8 位(单字节和)或低 16 位。
例,数据 01 03 00 0A:0x01 + 0x03 + 0x00 + 0x0A = 0x0E,单字节和补 0E。
注意同一串数据的 XOR 是 08、Sum 是 0E——两种算法结果不同,这正好可以反过来帮你判断设备用的是哪种:抓一条有效帧,两种都算一遍,哪个对上末位就是哪种。
CRC-16/Modbus:逐位法
CRC 手算最繁琐,但原理不复杂,走一遍你就懂它为什么抗错强。算法是:
- CRC 寄存器初值
0xFFFF。 - 取一个数据字节,与 CRC 的低 8 位异或,结果放回 CRC。
- 对 CRC 循环 8 次:检查最低位——若为 1,则 CRC 右移一位再异或
0xA001;若为 0,只右移一位。 - 所有数据字节重复 2–3。
- 最终 16 位就是 CRC,发送时低字节在前、高字节在后。
拿最经典的 Modbus RTU「读保持寄存器」请求验算,数据段 01 03 00 00 00 0A(地址 01、功能码 03、起始寄存器 0x0000、读 0x000A 个):
按上面步骤对 6 个字节逐一处理,最终:
CRC = 0xCDC5
帧尾发送顺序 = C5 CD (低字节 C5 在前,高字节 CD 在后)
完整帧 = 01 03 00 00 00 0A C5 CD
0xCDC5 你可以用任意 CRC 工具选「CRC-16/Modbus」核对,或用几行 Python 跑(初值 0xFFFF、多项式 0xA001、右移法),结果必须是 0xCDC5。实战没人真手算 CRC,都用库或工具;手算这遍的意义是让你确认三件事和设备对齐——多项式 0xA001、初值 0xFFFF、低字节先发,任一项不一致,算出来就对不上。
展厅实战用法
- 先确定校验范围:手册会标明校验从哪个字节算到哪个字节——含不含帧头?含不含地址字节?这一步错了,后面算法再对也白搭,因为你喂给算法的字节就不对。范围是校验排错第一顺位要确认的事。
- 核对 CRC 字节序:Modbus RTU 铁定低字节先发;私有协议没写清就抓一条手册给的示例报文,把校验位倒推回来验证顺序。
- 私有协议先抓一条正确帧:别对着手册干猜。用串口助手抓一条设备明确认可、能正常响应的完整帧,把三种校验都算一遍,反推出类型和范围,再批量套用到其它指令。这是私有协议最快的破解路子。
- 配合编码理解:校验作用在原始字节上,若手上是 ASCII 文本形式的指令,先还原成字节再算,别把字符显示值当字节值。
- 场景化封装:搞清校验后,展厅日常运营不该让操作员碰这些。把带正确校验的指令预存成设备控制动作,由 SoftControl 展厅中控 统一下发,中控内置多协议校验支持,替你把 CRC/Sum/XOR 的差异屏蔽在底层。这和 Modbus 协议速查 里”中控封装底层协议”的思路一致。
故障排查表
| 现象 | 可能原因 | 排查 / 解决 |
|---|---|---|
| 指令发出设备毫无响应、无报错 | 校验值算错,设备静默丢帧 | 抓有效帧倒推校验类型/范围,重算 |
| CRC 偶尔对偶尔错 | 高低字节发反(未固定低字节先发) | 固定 RTU 低字节在前,检查发送代码 |
| 校验范围里少算/多算了字节 | 含不含帧头/地址判断错 | 对照手册确认起止字节,重划范围 |
| 换了台同型号设备就失灵 | 两台设备校验配置(多项式/初值)不同 | 逐台核对多项式 0xA001、初值 0xFFFF |
| ASCII 协议校验总对不上 | 拿字符显示值当字节值算 | 先按编码还原成真实字节再校验 |
| 数据被干扰但校验竟然通过 | XOR 抗错弱,双位错互相抵消 | 高干扰环境优先选支持 CRC 的设备 |
排查口诀:发了没反应,先想校验;校验先查范围,再查字节序,最后才怀疑算法本身。 大多数”设备不理人”的私有串口故障都死在范围和字节序这两步。
进阶与边界
为什么 CRC 比 XOR/Sum 强? CRC 本质是把数据当成一个大二进制数、除以生成多项式取余数,这种”多项式除法”对连续多位翻转、突发错的敏感度远高于逐位异或或求和。XOR 最致命的软肋是两位同时翻转可能互相抵消、校验照过。所以工业级的 Modbus RTU 选 CRC-16 而非更省事的 Sum,是拿计算量换可靠性。
校验通过 ≠ 数据一定对。 任何校验都有理论漏检概率(不同错误碰巧算出相同校验值),只是 CRC 极低。它的定位是”低成本发现大部分错误”,不是保险箱。
Modbus 两种校验别混: RTU 帧用 CRC-16/Modbus,ASCII 帧用 LRC(求和取二进制补码)。传输模式不同校验就不同,接混必然对不上。
动手清单
对着一台带校验的设备排错,按顺序过:
- 抓到一条设备明确认可、能正常响应的完整有效帧
- 对这条帧分别算 XOR / Sum / CRC-16,确定它用哪种、末位对上哪个
- 确认校验范围:从哪个字节算到哪个字节,含不含帧头/地址
- 若为 CRC,核对多项式 0xA001、初值 0xFFFF、低字节先发三项
- 用同样算法给你要发的新指令算校验,发出去看响应
- 把带正确校验的指令固化进中控动作,别让运营手工拼帧
小结
校验是私有串口协议里最隐蔽的坑:算错的唯一现象就是”设备没反应”,和没接线几乎一样,却把你往错误方向带。记住三件事——校验只发现错误不改正、算法必须和设备完全一致(不能自选)、CRC-16/Modbus 铁律是低字节先发。真正高效的排错法不是对着手册猜,而是抓一条有效帧、用三种算法各算一遍倒推出真相。搞清之后,就把校验这件脏活交给中控封装,运营层只管触发场景。
延伸阅读:校验最常用在 Modbus 协议 上,也可查看 TCP/UDP 通信基础 与全部设备协议速查。
校验对不上是私有串口协议最隐蔽的坑。了解 SoftControl 展厅中控 内置的多协议校验支持,查看解决方案与落地案例,或直接联系我们聊聊你的定制需求。
留言讨论
评论发布后会被人工复核,违规内容将被删除。
如果发表没有反应,可以前往联系我们告诉我们。