为什么逐个读会慢
Modbus TCP 每次请求都有网络往返开销。假设要读 20 个分散在 40001~40020 的寄存器,逐个读要 20 次往返;而一次批量读只需要 1 次。在无线或跨网段环境,差距尤其明显。
三个功能码先分清
- 01/02:读线圈/离散输入(位)
- 03:读保持寄存器(4x,可读可写)
- 04:读输入寄存器(3x,只读)
批量读的关键是 03/04 功能码支持一次读一段连续寄存器(一次最多 125 个)。
合并连续地址的思路
把点位按地址排序,把“地址间隔在一个报文能覆盖范围内”的点合并成一组读,再从返回的寄存器数组里按偏移取各自的值。
点位:40001,40002,40003,40010,40011
分组1:起始40001 数量3 → 一次读回
分组2:起始40010 数量2 → 一次读回
中间空洞较大时才拆成多组,避免一次读入太多无用寄存器。
数据类型与字节序
一个寄存器 16 位,32 位浮点数占 2 个寄存器,需要拼字。不同 PLC 的字节序(大小端、字序)不同,常见有 ABCD / CDAB / BADC / DCBA 四种,拼接错误会得到离谱的数值,这是新手最常踩的坑。建议在点位配置里显式声明字节序。
轮询周期建议
- 快速变化量(转速、位置):500ms~1s
- 慢变量(温度、压力):2~5s
- 配置参数:上电读一次即可,不必周期轮询
按变化快慢分周期,比“所有点同一周期”更省资源。
落地清单
- 点位按地址排序并自动分组
- 显式配置每个点的数据类型和字节序
- 按变化快慢分多个轮询队列
- 加通讯超时和失败计数,连续失败触发断线重连
开源实现可参考 libmodbus(C)、pymodbus(Python)、NModbus(C#),原理一致。