2. Modbus协议基础
Modbus 是工业自动化领域最广泛使用的串行通信协议之一,它的设计哲学非常朴素:一个主站、多个从站,主站问、从站答。理解这套主从架构与请求响应模型,是后续开发 RTU/TCP 驱动、调试现场设备、排查通信故障的根基。本节从通信角色、报文交互、功能码分类到数据模型与寄存器类型,逐层拆解 Modbus 协议的核心骨架。
一、主从架构:谁说话,谁应答
Modbus 网络采用单主多从的总线型结构。主站(Master,也称 Client)是唯一主动发起通信的一方,从站(Slave,也称 Server)只能被动响应,绝不主动发送数据。在 Modbus RTU 中,从站通过 1~247 的从站地址区分;在 Modbus TCP 中,则通过 IP 地址 + 单元标识符(Unit ID)定位目标设备。
这种架构带来两个关键约束:一是同一时刻总线上只能有一个主站,否则会出现报文冲突;二是从站之间不能直接通信,若两个从站需要交换数据,必须由主站分别读取后再写入,即“主站中转”。
二、请求响应模型:一次完整交互的四个阶段
无论 RTU 还是 TCP,一次 Modbus 交互都遵循“请求—响应”模型,可拆解为四个阶段:
- 主站组帧:主站根据目标从站地址、功能码、起始地址、数量等参数构造请求帧。
- 发送与等待:RTU 通过串口发送,TCP 通过 Socket 发送,随后主站进入等待响应状态,并启动超时计时。
- 从站解析与执行:从站校验地址、CRC/长度、功能码是否支持,然后读取或写入对应寄存器。
- 从站应答:正常时返回功能码 + 数据;异常时返回“功能码 | 0x80” + 异常码。
下面是一次读取保持寄存器的典型请求与响应示意(以 RTU 为例):
请求:01 03 00 00 00 02 C4 0B
从站地址 01 | 功能码 03 | 起始地址 0000 | 数量 0002 | CRC
响应:01 03 04 00 0A 00 14 7B 8F
从站地址 01 | 功能码 03 | 字节数 04 | 数据 000A 0014 | CRC
异常:01 83 02 C0 F1
从站地址 01 | 异常功能码 83 | 异常码 02(非法数据地址)
开发驱动时,超时时间、重试次数、帧间隔是三个必须显式配置的参数。RTU 中帧间至少需要 3.5 个字符时间的静默间隔来界定帧边界;TCP 则由 MBAP 头中的长度字段界定,不依赖时间间隔。
三、功能码分类:四类操作,一张表看清
功能码是 Modbus 的“动词”,决定从站执行什么操作。常用功能码可按操作对象分为四类:
| 功能码 | 名称 | 操作对象 | 读写属性 |
|---|---|---|---|
| 0x01 | 读线圈 | 线圈(Coil) | 读 |
| 0x02 | 读离散输入 | 离散输入(Discrete Input) | 读 |
| 0x03 | 读保持寄存器 | 保持寄存器(Holding Register) | 读 |
| 0x04 | 读输入寄存器 | 输入寄存器(Input Register) | 读 |
| 0x05 | 写单个线圈 | 线圈 | 写 |
| 0x06 | 写单个寄存器 | 保持寄存器 | 写 |
| 0x0F | 写多个线圈 | 线圈 | 写 |
| 0x10 | 写多个寄存器 | 保持寄存器 | 写 |
功能码最高位为 1 时表示异常响应,例如 0x03 的异常响应为 0x83。异常码常见有:01 非法功能、02 非法数据地址、03 非法数据值、04 从站设备故障、05 确认、06 从站忙。
四、数据模型与寄存器类型:四个独立地址空间
Modbus 将数据抽象为四个相互独立的地址空间,每个空间有自己的地址范围,互不重叠。这是初学者最容易混淆的地方:同样是“地址 0”,在线圈、离散输入、输入寄存器、保持寄存器中代表完全不同的数据。
- 线圈(Coil):可读可写,1 位,常用于控制继电器、阀门、启停信号。
- 离散输入(Discrete Input):只读,1 位,常用于采集限位开关、按钮、故障触点。
- 输入寄存器(Input Register):只读,16 位,常用于采集温度、电压、电流等模拟量。
- 保持寄存器(Holding Register):可读可写,16 位,常用于设定值、参数配置、PID 目标值。
传统 Modbus 文档中常使用“5 位/6 位地址”表示法,例如 40001 表示保持寄存器第 1 个,30001 表示输入寄存器第 1 个。开发驱动时,协议帧中实际传输的是从 0 开始的偏移地址,因此 40001 对应帧内地址 0x0000,40002 对应 0x0001,务必注意“文档地址”与“协议地址”之间的换算。
五、案例与复盘:一次读温失败的分析
某现场使用 Modbus RTU 读取温度变送器,主站发送 01 04 00 00 00 01,从站无响应。排查过程如下:
- 确认从站地址:设备实际地址为 2,请求中写成了 1,地址不匹配导致从站静默丢弃。
- 确认功能码:温度变送器数据位于输入寄存器,应使用 0x04,而非 0x03。
- 确认串口参数:波特率 9600、8 数据位、无校验、1 停止位,与设备一致。
- 确认接线:A/B 线接反会导致电平翻转,表现为完全无响应或 CRC 错误。
修正后请求为 02 04 00 00 00 01,从站返回 02 04 02 00 FA,即温度值 250(0x00FA),按 0.1℃ 分辨率换算为 25.0℃。这个案例说明:地址、功能码、串口参数、接线是 Modbus 调试的四道关卡,任何一道出错都会表现为“无响应”或“异常码”。
掌握以上四点后,再看任意 Modbus 设备手册,都能快速定位到“用哪个功能码、访问哪个数据区、地址如何换算”。这是驱动开发中编写请求构造、响应解析、异常处理三部分代码的直接依据。