串口校验速查(CRC / 累加和 Sum / 异或 XOR)

2026-09-02

依据 Modbus 公开规范与常见串口约定整理。校验位本身不修复数据,只用于接收方判断帧是否被破坏。

从一条”发出去却石沉大海”的指令说起

调试一台带私有 HEX 协议的中控设备,你照着手册把开机指令一字节不差敲进串口调试助手,回车——设备毫无反应。你开始怀疑波特率、怀疑接线、怀疑设备坏了,折腾半小时,最后发现是末尾那两个校验字节的高低位发反了。设备收到帧后一算校验对不上,认定这帧被破坏,直接静默丢弃,连个错误码都不给。这就是校验类故障最阴的地方:它不报错,只是”没反应”,把你往完全错误的方向带。这篇把展厅最常遇到的三种校验——异或 XOR、累加和 Sum、CRC-16/Modbus——讲清楚,给你能拿计算器逐字节验算的实例。

校验是什么、为什么要

串口(RS232/RS485)在长线、强干扰环境下,某一位电平可能被翻转,0x30 传着传着变成 0x31。接收方光看字节没法判断这是不是原始数据。于是协议在每帧末尾附一段校验值:发送方按约定算法算出校验、附在帧尾一起发;接收方收到后用同样算法把数据段重算一遍,比对末尾的校验值一致才认这帧有效,不一致就丢弃。

记住一个前提:校验只”发现”错误,不”改正”错误。 它不是纠错码,接收方一旦发现对不上,唯一动作就是丢弃整帧。展厅里 Modbus 设备、私有 HEX 协议的报文大多带校验,所以校验算错 = 设备直接丢弃指令、毫无响应,且不报错,现象和”没接线""波特率错”几乎一样,病根却完全不同。

速查:三种常见校验

校验长度算法概述典型用途字节序
CRC-16/Modbus2 字节多项式 0xA001,初值 0xFFFFModbus RTU低字节在前
累加和 Sum1~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 0A0x01 ^ 0x03 = 0x020x02 ^ 0x00 = 0x020x02 ^ 0x0A = 0x08 → 校验 08

累加和 Sum:直接相加

把范围内所有字节算术相加,按协议取低 8 位(单字节和)或低 16 位。

例,数据 01 03 00 0A0x01 + 0x03 + 0x00 + 0x0A = 0x0E,单字节和补 0E。 注意同一串数据的 XOR 是 08、Sum 是 0E——两种算法结果不同,这正好可以反过来帮你判断设备用的是哪种:抓一条有效帧,两种都算一遍,哪个对上末位就是哪种。

CRC-16/Modbus:逐位法

CRC 手算最繁琐,但原理不复杂,走一遍你就懂它为什么抗错强。算法是:

  1. CRC 寄存器初值 0xFFFF
  2. 取一个数据字节,与 CRC 的低 8 位异或,结果放回 CRC。
  3. 对 CRC 循环 8 次:检查最低位——若为 1,则 CRC 右移一位再异或 0xA001;若为 0,只右移一位。
  4. 所有数据字节重复 2–3。
  5. 最终 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 展厅中控 内置的多协议校验支持,查看解决方案落地案例,或直接联系我们聊聊你的定制需求

需要展厅软硬件方案或定制开发?

留言讨论

评论发布后会被人工复核,违规内容将被删除。

    还没有人评论,来说说你的看法

    如果发表没有反应,可以前往联系我们告诉我们。

    这个页面有问题?

    提交时会附带当前页面地址和浏览器信息,帮助我们定位问题。不填联系方式即为匿名。