2. Modbus 协议栈详解:物理层、数据链路层与应用层

Modbus 协议栈遵循 OSI 参考模型的分层思想,但在实际工业应用中只涉及物理层、数据链路层和应用层。理解这三层的职责与配合,是掌握 Modbus 数据采集的基础。

2.1 物理层:RS-232、RS-485 与 TCP

物理层定义了设备之间传输原始比特流的电气特性、机械接口和传输介质。Modbus 支持三种主流物理层实现:

特性 RS-232 RS-485 TCP (Ethernet)
传输方式 单端不平衡 差分平衡 基带/交换
最大距离 约 15 m 约 1200 m 100 m(UTP)
节点数量 1 对 1 最多 32 节点(标准) 理论无限制
拓扑结构 点对点 总线型 星型
抗干扰能力 弱 强 中(依赖交换机)
典型应用 短距离调试 工厂现场总线 上位机/云平台
选型建议: 现场设备分散、距离远、干扰大时优先选用 RS-485;上位机与 PLC 或网关之间推荐使用 TCP;RS-232 仅用于近距离调试或老旧设备对接。

2.2 数据链路层:主从架构与报文帧

Modbus 数据链路层采用严格的主从(Master/Slave)架构。在同一总线上,同一时刻只能有一个主站发起请求,从站只能响应主站的请求,不能主动发送数据。

主从通信规则

  • 主站(Master): 唯一能发起通信的节点,通常为 PLC、上位机或网关。
  • 从站(Slave): 被动响应,每个从站拥有唯一的地址(1~247)。
  • 轮询机制: 主站依次向各从站发送请求帧,从站回复响应帧。
  • 广播: 主站可向地址 0 发送广播帧,所有从站接收但不回复。

报文帧结构(RTU 模式)

字段 长度 说明
从站地址 1 字节 目标从站 ID(1~247)
功能码 1 字节 指定操作类型(读/写)
数据区 N 字节 寄存器地址、数量、数值等
CRC 校验 2 字节 循环冗余校验(低字节在前)
注意: RTU 模式要求帧内字符间隔小于 1.5 个字符时间,帧间间隔大于 3.5 个字符时间,否则从站可能误判帧边界。
Modbus 主从架构通信流程 主站 (Master) 从站 1 从站 2 从站 N 请求帧 响应帧 • 主站轮询从站 1 → 从站 1 回复 → 主站继续轮询从站 2 → 从站 2 回复 → ... • 同一时刻只有一对主从在通信,其他从站处于监听状态。 • 从站之间不能直接通信,必须通过主站转发。

2.3 应用层:功能码详解

应用层通过功能码(Function Code)定义具体的读写操作。功能码是 Modbus 协议的核心,决定了主站与从站之间交换的数据类型和操作方式。

常用功能码分类

类别 功能码 名称 操作对象 说明
位操作 0x01 读线圈 DO(数字输出) 读取 1~2000 个线圈状态
0x02 读离散输入 DI(数字输入) 读取 1~2000 个输入状态
字操作 0x03 读保持寄存器 AO(模拟输出) 最常用,读取 1~125 个寄存器
0x04 读输入寄存器 AI(模拟输入) 读取 1~125 个寄存器
0x06 写单个寄存器 AO 写入 1 个 16 位寄存器
0x10 写多个寄存器 AO 写入 1~123 个寄存器
常见误区: 功能码 0x03 和 0x04 都用于读取寄存器,但 0x03 对应保持寄存器(可读可写),0x04 对应输入寄存器(只读)。混淆两者会导致通信失败或数据错误。

功能码与数据模型对应关系

Modbus 定义了四种基本数据对象,每种对象由不同的功能码访问:

  • 线圈(Coil): 1 位,可读可写,对应功能码 0x01、0x05、0x0F。
  • 离散输入(Discrete Input): 1 位,只读,对应功能码 0x02。
  • 输入寄存器(Input Register): 16 位,只读,对应功能码 0x04。
  • 保持寄存器(Holding Register): 16 位,可读可写,对应功能码 0x03、0x06、0x10。
Modbus 应用层:功能码与数据模型映射 数据模型 线圈 (Coil) - 1 bit 离散输入 (DI) - 1 bit 输入寄存器 (AI) - 16 bit 保持寄存器 (AO) - 16 bit 功能码 0x01 读 / 0x05 写单 / 0x0F 写多 0x02 读 0x04 读 0x03 读 / 0x06 写单 / 0x10 写多 关键规则 • 每个功能码对应固定的 数据模型和操作权限 • 功能码 0x03 是最常用的

2.4 协议栈分层协作示例

以下是一个完整的 Modbus RTU 读取保持寄存器请求帧示例,展示三层如何协作:

从站地址: 0x11  (17)          ← 数据链路层:目标从站
功能码:   0x03                ← 应用层:读保持寄存器
起始地址: 0x00 0x6B           ← 应用层:寄存器地址 107
寄存器数: 0x00 0x03           ← 应用层:读取 3 个寄存器
CRC 校验: 0x76 0x87           ← 数据链路层:帧校验

物理层负责将上述字节流转换为 RS-485 差分信号或 TCP 数据包,通过总线传输到目标从站。从站解析后返回对应数据。

实战要点: 在编写采集程序时,只需关注应用层的功能码和寄存器地址,物理层和数据链路层的细节通常由串口库或 Modbus 协议栈库封装。但理解底层机制有助于排查通信故障,例如 CRC 校验错误、地址冲突、波特率不匹配等。