3. Modbus RTU详解

Modbus RTU 是工业现场最常见的串行通信协议之一,它运行在 RS-485 或 RS-232 物理层之上,以紧凑的二进制帧、明确的地址机制和可靠的 CRC 校验,支撑着 PLC、仪表、变频器、网关之间的数据交换。理解 RTU 的关键,不只是记住功能码,而是把“串行通信基础—帧结构—CRC 校验—波特率与字符格式”串成一条完整的工程链路。

一、串行通信基础:RTU 为什么依赖 RS-485

Modbus RTU 本身是应用层协议,它并不规定电气特性,而是把字节流交给串行物理层传输。工程中最常见的是 RS-485 两线制半双工总线:主站发送请求,从站应答,同一时刻总线上只能有一个发送方。RS-485 采用差分信号 A/B 线,抗共模干扰能力强,适合几十米到上千米的工业现场。RS-232 则多用于点对点、短距离调试。

RTU 的“串行”意味着数据按位依次传输,因此波特率、数据位、停止位、校验位必须与从站严格一致。只要有一项不匹配,接收方就会在起始位、字节边界或校验阶段出错,表现为超时、乱码或 CRC 错误。现场调试时,先确认物理层 A/B 是否接反、终端电阻是否接入、屏蔽层是否单端接地,再检查串口参数,往往比直接怀疑协议更有效。

RS-485 总线两端通常各接 120Ω 终端电阻;手拉手拓扑优于星形拓扑,分支线越短越稳定。

二、RTU 帧结构:地址、功能码、数据与 CRC

Modbus RTU 帧没有起始符和结束符,它依靠“静默间隔”划分帧边界:帧内字节间隔不得超过 1.5 个字符时间,帧与帧之间至少需要 3.5 个字符时间的静默。帧结构如下:

字段长度说明
从站地址1 字节0x01~0xF7 为有效从站地址,0x00 为广播
功能码1 字节如 0x03 读保持寄存器、0x06 写单寄存器
数据域N 字节寄存器地址、数量、字节数或写入值
CRC 校验2 字节低字节在前,高字节在后

以读取从站 1 的 40001~40002 两个保持寄存器为例,请求帧为:

01 03 00 00 00 02 C4 0B
地址  功能码  起始地址  数量   CRC

从站正常应答:

01 03 04 00 0A 00 14 9B F1
地址 功能码 字节数 数据1 数据2  CRC

如果从站返回异常,功能码最高位置 1,并附带异常码,例如 01 83 02 C0 F1 表示功能码 0x03 异常,异常码 0x02 为“非法数据地址”。

三、CRC 校验:RTU 的完整性防线

CRC-16/Modbus 使用多项式 0xA001(反向表示),初始值为 0xFFFF。发送方对“地址+功能码+数据”逐字节计算,得到 16 位校验值,低字节先发、高字节后发。接收方重新计算并比对,若不一致则丢弃整帧,不返回任何应答,主站最终表现为超时。

CRC 计算的核心逻辑如下:

crc = 0xFFFF
for byte in data:
    crc ^= byte
    for _ in range(8):
        if crc & 0x0001:
            crc = (crc >> 1) ^ 0xA001
        else:
            crc >>= 1
return crc  # 低字节先发送

工程中常见误区是“CRC 高低字节顺序写反”。很多串口调试工具显示的是寄存器值,而实际发送顺序是低字节在前。若用软件模拟从站,必须按低字节先发;若用现成库,则要确认库函数是否已经处理字节序。

CRC 错误通常不是“协议不兼容”,而是波特率偏差、干扰、线缆过长、终端电阻缺失或字节间隔超时导致。先抓原始字节流,再判断是帧结构问题还是电气问题。

四、波特率与字符格式:参数必须完全一致

RTU 的字符格式通常表示为“波特率-数据位-校验位-停止位”,例如 9600-8-N-1 表示 9600bps、8 数据位、无校验、1 停止位。常见组合还有 19200-8-E-1、38400-8-N-1。每个字符包含起始位、数据位、校验位和停止位,因此实际传输一个字节需要 10 或 11 位。

波特率决定位时间。以 9600bps 为例,1 位约 104.17μs,一个 11 位字符约 1.15ms。3.5 个字符静默约 4ms,1.5 个字符约 1.7ms。若主站轮询周期过短,或从站响应慢,就会破坏帧边界。高波特率下,线缆电容和反射影响更明显,RS-485 总线长度与波特率通常成反比。

Modbus RTU 帧结构与串行字符格式 ① RTU 帧结构(以 0x03 读保持寄存器为例) 从站地址 1 字节 功能码 1 字节 数据域 起始地址 + 数量 / 字节数 + 数据 CRC 校验 2 字节,低字节先发 发送顺序:地址 → 功能码 → 数据 → CRC 低字节 → CRC 高字节 ② 帧边界:静默间隔 ≥ 3.5 字符静默 RTU 帧(字节间隔 ≤ 1.5 字符) ≥ 3.5 字符静默 ③ 串行字符格式:9600-8-N-1(1 个字符 = 10 位) 起始位 1 位 数据位 D0 ~ D7 8 位,低位先发 校验位 N/E/O 停止位 1 或 2 位 位时间:9600bps ≈ 104.17μs;1 个 10 位字符 ≈ 1.04ms;3.5 字符静默 ≈ 3.65ms 工程要点:主从波特率、数据位、校验位、停止位必须完全一致;CRC 低字节先发。

五、案例与排障:从“读不到数据”到定位问题

某现场网关作为 Modbus RTU 主站,轮询 3 台温控仪表,配置为 9600-8-N-1。现象是第 1 台正常,第 2、3 台频繁超时。排查步骤:

  1. 用串口监听工具抓取原始字节,确认请求帧地址依次为 01、02、03,帧结构正确。
  2. 检查 RS-485 接线,发现第 2、3 台 A/B 接反,交换后通信恢复。
  3. 进一步观察发现总线末端未接 120Ω 终端电阻,长线反射导致偶发 CRC 错误,补接后稳定。
  4. 将轮询间隔从 20ms 调整为 50ms,避免从站响应未结束就发起下一帧。

这个案例说明:RTU 故障往往同时涉及协议层和物理层。先看帧结构、CRC 和地址,再看波特率、字符格式和总线拓扑,最后才考虑更换设备。

RTU 调试口诀:先看接线,再看参数;先抓字节,再算 CRC;先保静默,再提速度。

六、常见误区复盘

  • 把 RTU 当 ASCII:RTU 是二进制帧,没有冒号和 LRC,不要混用。
  • 忽略 3.5 字符静默:高波特率下静默时间很短,但低波特率下必须留足,否则从站无法分帧。
  • CRC 字节序写反:发送时低字节在前,接收校验时按同样顺序重组。
  • 广播地址滥用:0x00 广播不产生应答,不能用于需要读取数据的场景。
  • 参数“看起来一样”:校验位 N/E/O 和停止位 1/2 必须逐项核对,不能只看波特率。

掌握 RTU 的帧结构、CRC 计算和字符格式,是后续搭建 Modbus RTU/TCP 网关的基础。网关一侧要正确解析 RTU 帧,另一侧要映射为 TCP MBAP 报文,任何一端的参数偏差都会在数据流中放大为通信故障。