2. Modbus通信原理精要

Modbus 是工业现场最广泛使用的应用层通信协议之一。它本身不规定物理层,而是定义了一套“请求—响应”式的报文规则:一台设备作为主站发起询问,其余设备作为从站被动应答。理解 Modbus,关键不是记住某个功能码,而是把主从架构、帧结构、寄存器映射和异常响应这四件事串成一条完整的通信链路。

一、主从架构:谁说话、谁应答

Modbus 采用严格的主从(Master/Slave)模型。同一时刻,总线上只能有一个主站发起请求,从站不能主动发送数据。主站发出请求后,从站根据请求中的“从站地址”判断是否属于自己:地址匹配则处理并返回响应,不匹配则忽略。这种机制避免了总线冲突,但也意味着通信效率受主站轮询节奏控制。

在串行链路(RTU/ASCII)中,从站地址范围为 1~247,0 为广播地址,广播请求不要求从站应答;在 TCP 链路中,从站地址通常称为“单元标识符(Unit ID)”,用于区分同一 IP 下的多个逻辑设备。主站轮询时,一般按“请求—等待—响应—超时重试”的节奏推进,超时时间需大于从站最大响应时间,否则会误判为掉线。

Modbus 主从通信与帧结构关系 主站 Master 发起请求 / 轮询 超时重试 / 异常处理 请求 → 总线 → 响应 从站 01 地址匹配 → 应答 从站 02 地址不匹配 → 忽略 从站 03 异常 → 异常码响应 RTU 帧结构(串行) 地址 功能码 数据域 CRC 校验 TCP 帧结构(以太网) MBAP 头 单元 ID 功能码 数据域 (无 CRC,由 TCP 保证)

二、RTU 与 TCP 帧结构差异

Modbus RTU 帧由四部分组成:从站地址(1 字节)、功能码(1 字节)、数据域(N 字节)、CRC 校验(2 字节)。帧与帧之间依靠至少 3.5 个字符时间的静默间隔来界定,因此波特率、数据位、校验位、停止位必须与从站一致,否则会出现“帧边界识别错误”。CRC 采用多项式 0xA001 逐位计算,低字节在前、高字节在后。

Modbus TCP 则把 RTU 的地址和 CRC 替换为 MBAP 报文头,共 7 字节:事务标识符(2 字节)、协议标识符(2 字节,固定 0)、长度(2 字节)、单元标识符(1 字节)。事务标识符由主站递增分配,用于把响应与请求配对;长度字段表示后续字节数。TCP 本身提供可靠传输,因此不再需要 CRC。实际工程中,串口服务器常把 RTU 帧“透明转换”为 TCP 帧,此时单元标识符通常沿用原从站地址。

三、功能码:请求做什么

功能码决定从站执行哪类操作。常用功能码可分为位操作和寄存器操作两类:

  • 01(读线圈):读取可读写开关量状态,如继电器输出。
  • 02(读离散输入):读取只读开关量,如限位开关。
  • 03(读保持寄存器):读取可读写 16 位寄存器,最常用于参数、测量值。
  • 04(读输入寄存器):读取只读 16 位寄存器,如模拟量采集值。
  • 05(写单个线圈)、06(写单个寄存器):单点写入。
  • 15(写多个线圈)、16(写多个寄存器):批量写入。

请求报文中,功能码之后通常跟起始地址(2 字节)和数量(2 字节)。例如读取从站 1 的保持寄存器 40001~40002,功能码 03,起始地址 0x0000,数量 0x0002。响应报文则先返回功能码,再返回字节数,最后是数据内容。注意:协议中的地址是“偏移地址”,而工程文档常写“40001”这类 1 基地址,编程时需减 1 转换。

四、寄存器映射:地址与数据含义

Modbus 只规定“寄存器编号”,不规定每个寄存器代表什么。设备厂商通过寄存器映射表定义含义。常见四类区域如下:

区域功能码典型地址读写示例
线圈 Coil01/05/1500001~读写启停命令
离散输入0210001~只读故障触点
输入寄存器0430001~只读温度测量值
保持寄存器03/06/1640001~读写设定值、参数

映射表通常还会标注数据类型:16 位整数、32 位整数、浮点数、位域等。32 位数据需要占用两个连续寄存器,且存在“高字在前”或“低字在前”两种字节序,必须按设备手册处理。例如某温度变送器 40001 为温度值,单位 0.1℃,读到 0x00FA 即 250,表示 25.0℃。若读到 0x8000 以上,可能表示负温度,需按有符号数解释。

五、异常响应机制:出错时怎么回

当从站无法正常处理请求时,不会沉默,而是返回异常响应。异常响应的功能码为“原功能码 + 0x80”,随后跟 1 字节异常码。例如请求功能码 03,异常响应功能码为 0x83。常见异常码包括:

  • 01 非法功能:从站不支持该功能码。
  • 02 非法数据地址:请求的寄存器地址超出映射范围。
  • 03 非法数据值:写入的值超出允许范围。
  • 04 从站设备故障:从站内部执行失败。
  • 05 确认:从站已接收,需较长时间处理。
  • 06 从站忙:从站正在处理长任务,主站应稍后重试。

主站收到异常响应后,应记录异常码并决定重试或报警。若主站长时间收不到任何响应,则属于超时,通常由地址错误、链路断开、波特率不匹配或从站未上电引起。实际调试时,可先用 Modbus Poll、QModMaster 等工具手动发一帧,观察返回的是正常数据、异常码还是超时,再逐项排查。

调试提示:串口 RTU 调试时,先确认 A/B 线极性、终端电阻和共地;TCP 调试时,先确认 IP、端口 502、单元 ID 与从站地址一致。异常码 02 往往说明地址偏移算错,异常码 03 则要检查写入值是否超出寄存器定义范围。

把以上五部分连起来看:主站按功能码构造请求,经 RTU 或 TCP 帧封装后发往目标从站;从站依据寄存器映射执行读写,正常则返回数据,异常则返回带 0x80 标志的异常码;主站根据响应类型判断通信结果。掌握这条链路,后续无论是配置网关、编写轮询程序,还是排查现场通信故障,都能快速定位问题发生在哪一层。