文章目录
- 一文看懂 Modbus:从零到能用
-
- Modbus 是啥?
- 四类“对象”、编号与功能码(核心概念)
-
- 参考号 vs 实际地址(偏移)
- RTU/ASCII/TCP 报文长啥样?
-
- RTU(串口,二进制)
- ASCII(串口,文本)
- TCP(以太网)
- 读写能带多少数据?(常用上限)
- 真·一眼会的实战例子
-
- 例子 1:读保持寄存器 40100(一个寄存器)
- 例子 2:写线圈 00020 为 ON
- 例子 3:连续读取离散输入 10001–10016(16 位)
- 例子 4:读取 32 位浮点数(占两个 HR)
- 连接与布线小抄(RS-485)
- 小细节 & 易踩坑合集
- 报文长相(看一眼就会)
- 选 RTU 还是 TCP?
- 上手代码(Python,pymodbus)
- 调试与工具清单
- 结语
一文看懂 Modbus:从零到能用
这篇给刚入门的你:什么是 Modbus、RTU/ASCII/TCP 有啥区别、寄存器和功能码怎么对上、报文长啥样、线缆怎么接、常见坑怎么避。看完你就能读/写设备数据,少踩 80% 的坑。
Modbus 是啥?
Modbus 是一种主从(Client/Server)式工业通信协议,用来在 PLC、变频器、仪表、传感器之间读写位或寄存器。它轻量、简单、跨品牌通用,至今仍是“现场总线界的英语”。
三种常见形态:
- Modbus RTU:跑在串口(常见 RS-485),二进制帧,效率高。
- Modbus ASCII:也跑串口,文本帧,易读但效率低。
- Modbus TCP:跑以太网(TCP 502 端口),好接入上位机/网络。
四类“对象”、编号与功能码(核心概念)
Modbus 操作的是 4 种对象(可理解为 4 个抽屉)——每类对象固定对应功能码(要干什么)和地址空间(在哪儿干):
0xxxx(如 00001) | Coils(线圈) | 位,读写 | 读 01 / 写单点 05 / 写多点 15 |
1xxxx(如 10001) | Discrete Inputs(离散输入) | 位,只读 | 读 02 |
3xxxx(如 30001) | Input Registers(输入寄存器) | 16 位,只读 | 读 04 |
4xxxx(如 40123) | Holding Registers(保持寄存器) | 16 位,读写 | 读 03 / 写单个 06 / 写多个 16 |
为啥“看地址就能知道功能码”?因为很多手册里的“地址”其实是带分类的参考编号(首位 0/1/3/4 已经说明了它属于哪个抽屉),而各抽屉的读写动作在协议里固定映射成上述功能码。
参考号 vs 实际地址(偏移)
真正进报文用的是0 基偏移地址,不是“40001”这种参考号。换算规则:
- Coil:偏移 = 参考号 − 1(00020 → 19)
- DI:偏移 = 参考号 − 10001
- IR:偏移 = 参考号 − 30001
- HR:偏移 = 参考号 − 40001
有些手册直接给“Address/Offset=99(0x0063)”这类0 基偏移,这时不用再减。以手册的列名为准。
RTU/ASCII/TCP 报文长啥样?
RTU(串口,二进制)
- 帧:[从站地址][功能码][数据…][CRC16]
- 以静默间隔划帧:帧前后至少 3.5 个字符时间(俗称 T3.5),帧内字节间不超过 1.5 个字符时间(T1.5)。
- 广播地址 0 只用于写(无应答,常用于同时下发)。
ASCII(串口,文本)
- 帧:: 开头,内容是 ASCII 十六进制,结尾 CRLF,LRC 校验。调试友好,效率较低。
TCP(以太网)
- 帧:[MBAP 头 7B][功能码][数据…] MBAP 头含事务 ID、长度、Unit ID(网关场景下映射到下挂 RTU 从站地址;直连设备通常忽略或设成 1/0xFF)。
- 无 CRC(由 TCP 保证)。
读写能带多少数据?(常用上限)
- 读 Coils/DI:最多 2000 位
- 读 IR/HR:最多 125 个寄存器
- 写多个 Coils(FC15):最多 1968 位
- 写多个 HR(FC16):最多 123 个寄存器
这些上限来自 Modbus PDU 的最大长度限制,绝大多数设备遵守。个别厂家可能更小——看手册。
真·一眼会的实战例子
例子 1:读保持寄存器 40100(一个寄存器)
- 类型:HR → 功能码 03
- 偏移:40100 − 40001 = 99
- 数量:1
- RTU 命令关键字段:[addr][03][00 63][00 01][CRC]
例子 2:写线圈 00020 为 ON
- 类型:Coil → 功能码 05
- 偏移:20 − 1 = 19
- 数据:ON=0xFF00(OFF=0x0000)
例子 3:连续读取离散输入 10001–10016(16 位)
- 类型:DI → 02
- 偏移:10001 − 10001 = 0
- 数量:16
例子 4:读取 32 位浮点数(占两个 HR)
- 文档说“40100(低字) 和 40101(高字) 组成一个浮点”
- 读参数:FC 03,偏移 99,数量 2
- 解析时注意字/字节序(常见:高低字交换 / 大小端不一致)。
连接与布线小抄(RS-485)
- 拓扑:总线型(菊花链),避免星形。
- 终端电阻:两端各 120 Ω;偏置电阻在一处提供。
- 屏蔽与接地:屏蔽层一端接地,注意共模干扰与等电位。
- A/B 命名混乱:不同厂家对 A/B(D+/D−)定义可能反着来;不亮就对调试试。
- 波特率:9600 很常见;更高波特率对线缆与干扰更敏感。
- 设备数量:传统 32 单位负载,现代收发器可更多(看手册)。
小细节 & 易踩坑合集
40001 并不是“真实地址” 真实的是偏移(0 基)。参考号只是带分类的“人类友好编号”。
-1 不是通吃 只有 0xxxx(Coil)是 −1;其余要减 10001/30001/40001。 个别厂商用 40000/30000 起步,是否 −1 以手册为准。
从站地址 ≠ 寄存器地址 从站地址(Unit/Slave ID)是哪台设备;寄存器地址是那台设备里的哪个点。
32 位/浮点的“字节序/字序” 两个 16 位寄存器拼 32 位可能需要 word swap / byte swap。不同厂家不同——看“字节序”说明或示例值。
广播写(地址 0)无应答 只在 RTU/ASCII;只能用于写类功能码(如 05/06/15/16),不要指望有响应。
异常码(错误码)读得懂,排错快 常见:
- 01:Illegal Function(功能不支持)
- 02:Illegal Data Address(地址不存在/越界)
- 03:Illegal Data Value(数量/参数不合法)
- 04:Server Device Failure(设备内部错误)
- 06:Server Device Busy(忙)
- 0A/0B:网关路径/下位机无响应(TCP→RTU 网关场景)
安全性 Modbus 无认证/加密。TCP 场景下请隔离网络、用 VPN/防火墙/网关做访问控制。
报文长相(看一眼就会)
以“从站 1 读取 3 个 HR,自偏移 0x006B(=寄存器 40001+0x006B=40108)”为例:
- RTU 请求:01 03 00 6B 00 03 CRClo CRChi
- RTU 应答:01 03 06 02 2B 00 00 00 64 CRClo CRChi 其中 06 表示后面有 6 个数据字节(3 个 16 位寄存器)。
你不必死记硬背,知道结构就能看懂:[地址][功能码][起始地址][数量] / [地址][功能码][字节数][数据…]。
选 RTU 还是 TCP?
- 已有很多串口设备/距离不长/干扰可控 → RTU(成本低)
- 要进上位机/云/广域网/易集成 → TCP(好接入、好管理)
- 混合:用 TCP→RTU 网关 把老设备接入以太网。
上手代码(Python,pymodbus)
RTU 读两个保持寄存器(从 40001 起)
from pymodbus.client import ModbusSerialClient
client = ModbusSerialClient(
port='COM3', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=1
)
client.connect()
res = client.read_holding_registers(address=0, count=2, slave=1) # 40001-40002
if not res.isError():
print(res.registers) # [reg0, reg1]
client.close()
TCP 写单个保持寄存器(40100 = 1234)
from pymodbus.client import ModbusTcpClient
client = ModbusTcpClient(host='192.168.1.10', port=502)
client.connect()
res = client.write_register(address=99, value=1234, slave=1) # 40100 → 偏移 99
print(res.isError())
client.close()
提示:很多设备 TCP 场景下会忽略 slave(Unit ID),但网关需要这个值来路由到下挂 RTU 从站。
调试与工具清单
- 串口参数:波特率/数据位/校验/停止位必须一致(常见 9600 8N1)。
- 测试软件:Modbus Poll/QModMaster(主站)、Modbus Slave(从站仿真)。
- 抓包:TCP 用 Wireshark;串口用串口监听工具或 USB 逻辑分析仪。
- 逐步法:先“读一个”成功→再“读一批”→最后“写入”。
结语
Modbus 的精髓就是:四类对象固定映射功能码,报文里用 0 基偏移。认清“参考号 vs 偏移”的区别,你就能在各家设备间自如切换。
评论前必须登录!
注册