4. Modbus协议详解与电表接入实战
Modbus 是 SCADA 能源管理系统中使用最广泛的现场总线协议之一,它简单、开放、易于实现,几乎所有电表、PLC、RTU 都支持。本节从帧结构入手,逐步展开到功能码、寄存器映射、轮询策略,最后用工具实际读取一台电表的数据,形成完整的接入闭环。
一、Modbus RTU 与 TCP 的帧结构差异
Modbus 有两种常见承载方式:串行链路上的 RTU 模式和以太网上的 TCP 模式。两者应用层协议数据单元(PDU)完全一致,区别在于外层封装。
RTU 帧由地址、功能码、数据、CRC 校验组成,帧与帧之间靠至少 3.5 个字符时间的静默间隔分隔。例如读取从站地址 1 的保持寄存器 0x0000 起 2 个寄存器,请求帧为:
01 03 00 00 00 02 C4 0B
│ │ │ │ └── CRC 低字节
│ │ │ └──────── 寄存器数量 = 2
│ │ └────────────── 起始地址 = 0x0000
│ └───────────────── 功能码 03(读保持寄存器)
└──────────────────── 从站地址 01
TCP 帧在 PDU 前增加 7 字节 MBAP 报文头:事务标识、协议标识、长度、单元标识。同样请求在 TCP 下为:
00 01 00 00 00 06 01 03 00 00 00 02
│ │ │ │ │ │ │
│ │ │ │ │ │ └── 数量 2
│ │ │ │ │ └──────── 起始地址
│ │ │ │ └─────────── 功能码 03
│ │ │ └────────────── 单元标识(从站地址)
│ │ └──────────────────── 后续字节数 = 6
│ └────────────────────────── 协议标识 0
└──────────────────────────────── 事务标识
RTU 依赖 CRC 保证完整性,TCP 则由以太网和 TCP 层保证,因此 MBAP 中不再有校验字段。理解这一点,就能在抓包时快速区分两种报文。
二、常用功能码与寄存器映射
电表接入最常用的功能码有四个:01 读线圈、02 读离散输入、03 读保持寄存器、04 读输入寄存器。电表测量值(电压、电流、功率、电能)通常放在保持寄存器或输入寄存器中,因此 03 和 04 使用频率最高。
寄存器映射是接入的核心。以一台典型三相多功能电表为例,其 Modbus 寄存器表可能如下(示例参数,实际以厂家手册为准):
| 寄存器地址 | 参数 | 数据类型 | 单位 | 换算系数 |
|---|---|---|---|---|
| 0x0000 | A 相电压 | UINT16 | V | ×0.1 |
| 0x0001 | B 相电压 | UINT16 | V | ×0.1 |
| 0x0002 | C 相电压 | UINT16 | V | ×0.1 |
| 0x000A | 总有功功率 | INT32 | kW | ×0.001 |
| 0x0010 | 正向有功电能 | UINT32 | kWh | ×0.01 |
注意两点:一是寄存器地址与协议地址的偏移,有些手册标 40001 对应 0x0000,有些标 1 对应 0x0000,需以手册说明为准;二是32 位数据占用两个连续寄存器,存在高低字顺序问题,常见为高字在前(Big-Endian),也有低字在前的情况,读回后需按手册拼接。
三、轮询策略
SCADA 采集多台电表时,轮询策略直接影响实时性和总线负载。核心原则是:合并连续寄存器、控制单次读取长度、合理分配轮询周期。
- 合并读取:若电压、电流、功率寄存器连续,用一次 03 请求读取整段,而不是逐点读取。例如从 0x0000 读 16 个寄存器,一次拿回全部电气量。
- 限制长度:单次读取一般不超过 125 个寄存器(Modbus 规范上限),实际建议不超过 60 个,避免响应超时。
- 分级周期:电压、电流等实时量用 1 s 周期;电能累计量变化慢,用 10~30 s 周期即可,减少总线压力。
- 超时与重试:RTU 下响应超时通常设 300~1000 ms,重试 2~3 次;连续失败应标记该从站离线,避免阻塞其他设备。
四、用工具读取电表数据
实际接入前,先用工具验证通信,再写采集程序。常用工具有 Modbus Poll(Windows)、mbpoll(Linux 命令行)、QModMaster 等。以 mbpoll 读取 RTU 电表为例:
mbpoll -m rtu -b 9600 -p none -d 8 -s 1 \
-a 1 -t 4 -r 1 -c 3 /dev/ttyUSB0
# -m rtu RTU 模式
# -b 9600 波特率 9600
# -p none 无校验
# -d 8 8 位数据位
# -s 1 1 位停止位
# -a 1 从站地址 1
# -t 4 读输入寄存器(03 为保持寄存器)
# -r 1 起始地址 1
# -c 3 读 3 个寄存器
若返回类似 [1]: 2201 2198 2205,按 ×0.1 换算即 A/B/C 相电压约 220.1 V、219.8 V、220.5 V,说明通信与映射均正确。若返回超时或异常码,先检查接线 A/B 是否反接、波特率与校验位是否一致、从站地址是否正确。
完成工具验证后,即可将相同的参数迁移到 SCADA 驱动的设备配置中:填写 IP/串口、从站地址、功能码、起始地址、寄存器数量、数据类型与换算系数,再设置轮询周期和超时重试,电表数据就能稳定进入能源管理平台。