Modbus 的从站地址冲突:最隐蔽的通信故障
Modbus Slave Address Conflict
Modbus RTU 网络里,两个设备设了相同地址,后果不是"通信失败",而是"间歇性乱码"——某些查询返回正确,某些返回错误设备的数据,调试到怀疑人生。
本文涉及的条目4 条 · 自动匹配自标签与标题
地址冲突怎么发生
Modbus RTU 是主从协议,主站发起查询,指定从站地址(1~247),只有该地址的从站应答。如果两个设备地址相同,两者都会应答——但应答数据在总线上叠加,造成 CRC 校验失败,主站收到乱码。
但冲突不一定每次都报错:
- 如果两个设备的寄存器映射相同、查询的寄存器地址相同,返回的数据可能"碰巧"一致,CRC 通过,主站读到正确格式的数据——但这是另一个设备的数据。
- 如果两个设备的应答长度不同(如一个返回 2 字节、另一个返回 4 字节),短的那个应答完了,长的还在发,总线冲突,CRC 失败。
所以冲突的症状是间歇性:偶尔正常、偶尔乱码、偶尔读到错误数据。这种间歇性让工程师怀疑线缆、接地、终端电阻,折腾很久才发现是地址冲突。
典型场景
- 多供应商集成:A 厂家设备默认地址 1,B 厂家设备也默认 1。集成商不重新分配地址就上线。
- 更换设备未改地址:原设备地址 5 损坏,新设备默认 1,没改回 5。
- 批量配置出错:用配置工具批量设地址,工具 bug 或操作漏掉一台,两台都是 7。
- 广播地址 0 误用:地址 0 是广播,所有从站都应答——如果有人把某设备设为 0,每次广播都会收到多个应答,总线彻底乱。
自检方法
方法一:单点查询扫描
主站依次查询地址 1~247,每个地址发一条读保持寄存器(功能码 03)查询。正常情况下,未配置的地址会超时无应答;配置的地址会快速应答。如果一个地址应答时间异常长或返回 CRC 错误,疑似冲突。
方法二:地址应答特征
冲突地址的应答有特征:
- 应答时间不稳定:正常从站应答时间 = 处理时间 + 帧间隔(3.5 字符时间)。冲突地址因为两个设备抢总线,应答时间波动大。
- CRC 错误率高:两个应答叠加,CRC 几乎必然错。如果某个地址的 CRC 错误率 > 5%,几乎可以确认冲突。
- 数据值跳变:同一寄存器连续两次读,数值差异远超合理范围——可能在两个不同设备间切换。
方法三:物理断开
最简单的现场办法:逐个拔设备。冲突地址的两个设备拔掉一个,通信立刻稳定——确认是这两个冲突。
预防
- 集成前生成地址分配表:每个设备一个地址,记录在文档里。新增设备先查表。
- 默认地址清单:要求每个供应商提供默认地址,集成时统一规划。
- 现场调试工具:用 Modbus 调试软件(如 Modscan、CAS Modbus)做"地址扫描",发现冲突。
- 避免使用地址 0:永远不用广播地址做业务查询,只用于写命令(写不需要应答)。
一个被忽视的细节:单元标识符
Modbus TCP 里没有从站地址(用 IP 地址),但有"单元标识符"(Unit Identifier)。很多人以为 TCP 模式下没有地址冲突——错。网关把 TCP 请求转 RTU 时,单元标识符就是 RTU 从站地址。两个网关下挂的设备如果单元标识符相同,TCP 主站查询时,两个网关都会转发,RTU 总线上仍然冲突。
所以 Modbus TCP 的"地址"也要管理,不能因为 TCP 是点对点就忽视。
结语
Modbus 地址冲突不是"通信失败",而是"间歇性乱码"——最隐蔽、最难调试的故障。预防胜于治疗:集成前做地址分配表,调试时做地址扫描,运行时监控 CRC 错误率。这三步能消除 90% 的 Modbus 网络调试之苦。