协议接入

Modbus 采集怎么做:五种变体、地址与字序

Modbus 是数采项目里出现频率最高的协议——国产 PLC、变频器、温控表、电表、称重仪表、气体检测仪基本都支持它。协议本身简单到一页纸能讲完,但现场出问题的比例并不低,问题几乎全在地址、字序和总线这三件事上。

Modbus 是什么,会在哪些设备上遇到

Modbus 是 1979 年 Modicon 为自家 PLC 定的一套主从式通信协议, 因为规范公开、实现简单,后来成了工业现场事实上的通用语言。 它的数据模型只有四个区:线圈(可读写位)、离散输入(只读位)、 保持寄存器(可读写 16 位字)、输入寄存器(只读 16 位字), 对应功能码 01/02/03/04 读,05/06/0F/10 写。整个协议没有数据类型、没有单位、 没有变量名——这既是它简单的原因,也是所有现场问题的根源。

在数采项目里,几乎每个现场都会遇到 Modbus 设备: 国产 PLC(汇川、信捷、台达、禾川等)多数把它作为默认的对外接口; 变频器与伺服驱动器用它读电流、转矩、频率与报警字; 温控表、称重仪表、压力/流量变送器、气体检测仪、环境监测模块基本只有 Modbus; 智能电表除了 DL/T 645 也常提供 Modbus; 还有大量国产的智能仪表与传感器模块,铭牌上写的通信方式就是 RS485 Modbus-RTU。 敏洽 SCADA 数采软件 为 Modbus 提供了 modbus_tcp、modbus_rtu、 modbus_rtu_over_tcp、modbus_ascii、modbus_udp 五个独立驱动,串口类驱动自动独占线程,避免多个实例抢同一个串口。

五种变体怎么选

驱动承载与校验什么时候用它
modbus_tcpTCP/502,MBAP 帧头,无 CRC设备有网口且明确支持 Modbus TCP。首选,最省事
modbus_rtuRS485/RS232,CRC16设备只有串口,且采集端(工控机或网关)就在柜内或附近
modbus_rtu_over_tcpTCP 透传 RTU 原始帧,保留 CRC485 设备经串口服务器接到以太网。老站改造最常用
modbus_ascii串口,ASCII 编码,LRC 校验部分早期温控表与称重仪表只支持 ASCII 模式
modbus_udpUDP 承载少数设备只开 UDP;对时延敏感且能容忍偶发丢包的场合

最容易配错的是 RTU over TCP 与 Modbus TCP: 两者都是「往 TCP 连接里发 Modbus」,但帧格式不同—— 前者是带 CRC 的 RTU 帧,后者是带 MBAP 头不带 CRC 的 TCP 帧。 串口服务器工作在透传模式时给出的是 RTU 帧,必须用 modbus_rtu_over_tcp; 部分串口服务器有「协议转换」模式,能把 Modbus TCP 翻成 RTU, 这时候采集侧才用 modbus_tcp。配错的现象是连接能建立、发出去没有正确应答, 很容易被误判成设备不通。

实际会遇到的几个坑

1. 地址基准:4xxxx 编号与报文偏移量差 1

手册写 40001,报文里发的是 0。这套 4xxxx 编号来自早期 Modicon 文档, 4 表示保持寄存器区,后面五位从 1 开始编号;而协议报文传的是从 0 开始的偏移量。 各家手册在这一点上写法不统一,甚至同一份手册前后不一致。 症状是所有数据整体错开一个位置, 如果相邻地址的数据类型相同,读出来的数看着都合理,能一路错到验收。 判断动作:找一个已知会变的点(产量计数器最好用), 让设备动作一次,看变化落在哪个地址上,以此校准整张点表的基准。

2. 寄存器区选错:03 码与 04 码

保持寄存器(功能码 03)与输入寄存器(功能码 04)是两个独立的地址空间, 地址 100 在两个区里是完全不同的数据。很多仪表把测量值放在输入寄存器、 把参数放在保持寄存器,手册里只写「寄存器 30001」这类编号, 3xxxx 才是输入寄存器区,4xxxx 是保持寄存器区。选错的表现分两种: 设备严格实现协议时返回非法数据地址异常(异常码 02),比较好查; 设备实现得松散时直接把另一个区的值给你,就变成上一条那种「不报错但数值不对」。 同理还有线圈(01)与离散输入(02)这一对。

3. 32 位数与浮点数的字序有四种排列

Modbus 的寄存器是 16 位,32 位整数与单精度浮点占两个寄存器, 但协议没规定哪个寄存器放高位,加上寄存器内字节序也可能翻转, 实际会遇到四种排列。症状是数值的数量级完全不对,或者小数点位置离谱, 有时甚至读出 NaN。 正确做法是用一个已知值反推: 把计数器置到 1000,或者读一个已知量程的模拟量,四种排列各算一遍, 能对上的那一种就是设备的字序。确认后必须写进点表, 同一台设备上不同厂家的模块字序还可能不一样。 同类问题还有有符号与无符号:温度这类可能为负的量按无符号解析, 零下就变成六万多。

4. 一次读多少:单次请求的寄存器上限与批量读

Modbus 单次读保持/输入寄存器最多 125 个(读位最多 2000 个), 超出会返回非法数据数量异常。更实际的问题是请求次数: 如果点表里的地址东一个西一个,采集侧就得发很多次请求, 485 上每次请求都要等应答,节拍立刻上去了。 解决办法是在项目初期就要求设备厂 把需要外发的数据整理到一段连续的寄存器区, 采集侧一次批量读完再在本地拆分。这属于设备厂改 PLC 程序的工作量, 要在接口确认阶段提出来,不能等联调时才说。 另外有些设备虽然协议上支持 125 个,实际读超过一定数量就超时, 这种只能实测找出安全值。

5. 485 总线的物理问题:接反、无终端电阻、与动力线同槽

串口类 Modbus 的故障里,相当一部分根本不在协议层。 A/B 两根线接反是最高频的,现象是完全没有应答, 不报错也不返回错帧,和线没接一样,不确定就直接对调试一次。 其次是拓扑:485 必须手拉手串接,不能星形分叉; 总线两端各需一个 120Ω 终端电阻,距离长、波特率高时缺电阻会造成随机误码; 屏蔽层单端接地。最难查的是与动力线、变频器输出线同槽走线, 表现是平时好用、大功率设备启停时集中报错, 这种「时好时坏」几乎总被先怀疑成软件问题。

6. 从站地址、波特率与帧参数四件套不匹配

串口 Modbus 需要从站地址(1~247)、波特率、数据位、停止位、校验位全部一致, 任何一项不对都是没有应答。这里的坑是: 设备铭牌上的资产编号不是从站地址, 从站地址往往要在设备面板菜单里查或改; 一条总线上两个设备用了同一个从站地址时, 两台会同时应答造成帧冲突,现象是间歇性 CRC 错误, 比完全不通更难查。上线前应该逐台确认地址唯一。

7. 瞬时值与件级结果:必须有锁存和握手

采集端按周期轮询,寄存器里的值随时在变。 如果要的是件级数据(这一件的测量值、这一件的判定结果), 直接轮询瞬时寄存器一定会漏件或读到中间态,节拍快的工站尤其明显。 正确做法是让 PLC 在每件完成时把结果 锁存到固定寄存器,同时把一个序号或握手位加一, 采集侧监视序号变化再读结果区,读完回写确认。 这套机制要写进接口文档,由设备厂电控工程师在 PLC 程序里实现。

接入方式与硬件条件

项目要求与说明
首选接法设备支持 Modbus TCP:网线直接接入,驱动用 modbus_tcp,端口默认 502
串口接法485 直连采集端用 modbus_rtu;经串口服务器透传用 modbus_rtu_over_tcp
串口参数从站地址、波特率、数据位、停止位、校验位五项须与设备一致,且总线内地址唯一
485 布线手拉手串接、屏蔽双绞线、两端 120Ω 终端电阻、屏蔽层单端接地、与动力线分槽
寄存器规划要求设备厂把外发数据集中到连续区,单次读不超过 125 个寄存器
并发限制485 只允许一个主站;Modbus TCP 需确认设备并发连接数上限,建议只保留一路采集
件级结果需 PLC 侧锁存 + 序号/握手位,采集侧按序号变化触发读取并回写确认
点表必备字段名称、功能码/寄存器区、地址(注明是否 4xxxx 基准)、数据类型、字序、缩放系数、单位、位与枚举含义、更新频率

需要客户或设备厂准备的硬件是:设备侧的通信口(可能要加通信扩展模块)、 串口服务器(485 转以太网方案)、以及交换机端口与 IP 规划。 串口服务器与网关型号敏洽可以给建议, PLC 程序侧的寄存器规划与握手逻辑由设备厂的电控工程师实现。

相关交付情况

Modbus 现场的经验是:协议本身几乎不花时间, 全部工作量在点表质量与总线条件上。 所以敏洽的做法是项目一开始先发一份点表模板, 把功能码、地址基准、字序、缩放系数、位含义这些容易漏的列预置好, 由设备厂填完再评估工作量。 带调试面板的驱动可以在软件里直接发原始报文、看返回字节、逐点核对, 不需要另外准备第三方调试工具,联调阶段能省掉不少来回。

国产 PLC 的软元件与 Modbus 地址映射差异见 汇川、信捷、台达 PLC 采集; 只有串口甚至没有接口的老设备见 老旧设备联网; 读不到数据的排查顺序见 数据取不出来怎么排查。

常见问题

三者的应用层完全一样(功能码与寄存器语义相同),差别只在承载方式与校验。Modbus TCP 走以太网,帧头带事务标识符,用 TCP 自身的校验,端口默认 502。Modbus RTU 走 RS485/RS232 串口,帧尾是 CRC16。RTU over TCP 是把 RTU 的原始帧(含 CRC)塞进 TCP 连接里透传,通常出现在串口服务器后面。选择依据很直接:设备有网口且支持 Modbus TCP 就用 TCP;只有 485 口且采集端就在附近就用 RTU;只有 485 口但要接到远处的机房,就加串口服务器走 RTU over TCP。注意 RTU over TCP 与 Modbus TCP 不能混用,帧格式不同,配错了表现是完全没有正确应答。
这是 Modbus 最著名的坑。早期 Modicon 文档用 4xxxx 编号表示保持寄存器区,1 表示该区第一个寄存器;而协议报文里传的是从 0 开始的偏移量。所以手册上的 40001 对应报文里的地址 0,40100 对应 99。不同厂家的手册不统一:有的直接给报文地址,有的给 4xxxx 形式,有的写「寄存器号」却没说是哪一种。症状是所有数据整体错开一个位置,而且往往不报错。可靠的确认方法是找一个已知会变的点(产量计数器最合适),让设备动一下,看变化出现在哪个地址上。
Modbus 的寄存器是 16 位的,32 位数据占两个连续寄存器,但协议没有规定哪个寄存器放高 16 位——这是厂家自己定的。加上每个寄存器内部字节序也可能不同,理论上有四种排列(常说的 ABCD、CDAB、BADC、DCBA)。判断方法不要靠猜:让设备产生一个已知的值(比如把计数器置到 1000,或读一个已知量程的模拟量),把四种排列都算一遍,只有一种能对上。确认之后写进点表,不要留给下一个人重新试。
电气上标准 RS485 驱动器带 32 个节点,用 1/8 负载收发器可以到 128 个,但这只是电气上限,实际限制来自轮询节拍。485 是半双工单主站,采集端必须一问一答串行轮询:每个设备一次请求加应答按 9600bps 大约几十毫秒,挂 20 个设备一轮就要一秒以上。所以真正决定采集频率的是「设备数 × 每设备请求数 × 单次耗时」。要提高频率有三条路:提高波特率、要求设备把外发数据集中到连续寄存器区以便一次批量读(Modbus 单次最多读 125 个保持寄存器)、或者拆成多条 485 总线并行。
485 不行。RS485 是单主站总线,两个主站同时发请求会直接冲突,表现是双方都间歇性超时或收到错乱的帧。Modbus TCP 要看设备的并发连接数上限,很多嵌入式从站只允许 1~4 个连接,超了会拒绝或挤掉旧连接。稳妥做法是一台设备只保留一路采集,由这一路把数据分发给多个上层系统,而不是每个系统各连一次。
先区分两类:所有数据都不对,通常是地址基准(差 1)或者寄存器区选错(保持寄存器 03 码与输入寄存器 04 码搞混);只有部分数据不对,通常是这几个点的数据类型、字序或缩放系数写错了。Modbus 对地址只做范围校验不做语义校验,你要哪两个字节它就给你哪两个字节,是不是你想的那个变量协议不管,所以「不报错但数值离谱」几乎一定是点表问题,必须靠现场手动改值逐点核对。

有具体设备清单或工件样品,可以直接给判断

提供设备型号、PLC 品牌与需要采集的数据项,或提供被检工件照片与精度要求,敏洽可先给出可行性判断与硬件前置条件,再谈软件工作量与报价。