FB_MbMultiRead
Modbus TCP 主站 · 多从站自动轮询

一个实例管最多 8 个从站、32 条任务;读自动分片;同一从站可又读又写,共用一条连接。

西门子 S7-1500 · TIA Portal SCL · 基于系统指令 MB_CLIENT 封装 · 版本 v3.5

下载完整包(zip · 3 个 SCL 版本 + 配套全局 DB + 仿真脚本 + 导入指南)

3 种编码任选其一导入 TIA Portal · 包内 10 个文件

FB 必须配一张全局 DB
三个数据引脚 aSta / aTask / aBuf 是 VAR_IN_OUT, 块自己不存数据 —— 数组得从外面的全局 DB 传进来。包里已经备好一张现成的 DB_MbMultiRead,直接导入就能用,不用自己照着 UDT 手工建。

一、它解决什么问题

一个 PLC 要同时采几十台 Modbus TCP 从站,每个从站好几个数据区,还得往回写数据。用官方指令裸写,代码量能顶掉半个项目;用一个实例写死一个从站,实例数会失控。

对比项单任务版FB_MbMultiRead(本块)
一个实例管几个从站1 个最多 8 个
换从站要重连吗要(改 IP 得断开重连)不用,每个从站一条常连接
单次能处理的寄存器数125(超了要自己建多个实例)读自动分片,填 600 就分 5 帧
一个实例能配几条任务1 条最多 32 条
同一从站能否又读又写不能(要开两个实例=两条连接)能,共用一条连接
数据放哪外部数组 aData[0..124](InOut)外部数组 aBuf[0..999],各任务按 uBufOff 落位
适用平台S7-1500 / S7-1200S7-1500(用了 8 个 MB_CLIENT 实例)
这个包只发 FB_MbMultiRead 一个功能块(外加它必须的配套全局 DB)。同一套里的自由口主站、轮询调度、写缓存队列等块还在本地整理中,没测完的不往站上放。

二、三个典型场景

场景 A:读多个 IP 从站

从站表:aSta[1]=[192,168,0,51]  aSta[2]=[192,168,0,52]  aSta[3]=[192,168,0,53]
uTaskCount := 3

任务表:
  aTask[1]: uStaNo=1  bWrite=FALSE  uFunc=3  uAddr=0  uCount=100  uBufOff=0
  aTask[2]: uStaNo=2  bWrite=FALSE  uFunc=3  uAddr=0  uCount=100  uBufOff=100
  aTask[3]: uStaNo=3  bWrite=FALSE  uFunc=3  uAddr=0  uCount=100  uBufOff=200

读回:aBuf[0..99] / aBuf[100..199] / aBuf[200..299]

场景 B:同一个 IP 读 600 个寄存器

从站表:aSta[1]=[192,168,0,51],uTaskCount := 1
任务表:
  aTask[1]: uStaNo=1  bWrite=FALSE  uFunc=3  uAddr=0  uCount=600  uBufOff=0

块内自动切成 5 帧:125 + 125 + 125 + 125 + 100
读回:aBuf[0..599](aBuf[0] 就是寄存器 0)

有些网关只认 100 个/帧,把 uMaxRegs 从 125 降到 100,600 个就自动变 6 帧。

场景 C:同一个 IP 又读又写

关键是两条任务填同一个 uStaNo。它们共用那一条 TCP 连接,块内串行交替执行:读一帧 → 写一帧 → 再读一帧。

三、三个版本文件怎么选

文件编码用途
FB_MbMultiRead.sclUTF-8 + BOM阅读与留档(完整中文注释)
FB_MbMultiRead_EN.scl纯 ASCII首推导入版,最稳
FB_MbMultiRead_GB2312.sclGBK 无 BOM想看中文注释时用这版导入

_GB2312 是派生文件,由脚本自动生成。改了逻辑要改主文件后重新派生 —— 永远不要手工改 _GB2312,下次派生会全部覆盖。

四、导入步骤

  1. 项目树 → 外部源文件 → 添加新的外部源文件 → 选中 .scl → 从源生成块。
  2. 先在本页下好单文件(上面那些链接),选一个编码版本。
  3. 不要先手动新建同名块,否则会冲突。
  4. 生成后按需要建两张表:UDT_MbStation(从站表,下标 1..8 对应连接槽位)、UDT_MbTask(任务表,最多 32 条)。
  5. 再导入配套的全局 DB(DB_MbMultiRead.scl)—— 顺序不能反,见下节。

配套全局 DB:DB_MbMultiRead

本块的三个数据引脚是 VAR_IN_OUT,数组要从外部全局 DB 传进来。 包里备了一张现成的,结构和本块严格对得上:

DB 成员类型对应引脚用途
StationArray[1..8] of "UDT_MbStation"aSta从站表,下标即连接槽位号
TaskArray[1..32] of "UDT_MbTask"aTask任务表,最多 32 条
BufferArray[0..999] of WordaBuf数据总缓冲(读落点 / 写来源)
  1. 先导入 FB 源 → 从源生成块 → 三个(两个 UDT + FB)一起生成。
  2. 再导入 DB_MbMultiRead.scl → 从源生成块 → 只会列出 DB_MbMultiRead 一项 → 生成。
    顺序不能反:DB 用到了 FB 源里定义的两个 UDT,UDT 不在就报类型未知。
  3. OB1 里把 FB 拖进网络,三个引脚分别接到 "DB_MbMultiRead".Station / .Task / .Buffer。
  4. FB 的实例 DB(FB_MbMultiRead_DB)由博图自动生成,不用手工建。
成员名和引脚名不一样(Station ↔ aSta)是正常的 —— IN_OUT 按类型和长度匹配,不按名字匹配。
这张 DB 用了 NON_RETAIN(断电重启回到初始值)—— 这是故意的:IP、端口、任务表不该被留在 PLC 里。另外 Station[n].uUnitId 默认是 16#FF(255,MB_CLIENT 出厂值), 直连设备一般要改成 1。

配套的 verify_db_multiread.py 会逐项比对 DB 与 FB 的接口定义 (数组上下限、元素类型、两个 UDT 的全部字段名、边界),27 项检查全部通过。

升级老项目:光换 FB 不够

UDT 结构改过,任务 DB 必须重建再下载,不能只替换 FB 就完事 —— 老结构里字段对不上位置,运行时会读到错位的值。

五、三个必须知道的约束

1. 占用连接 ID 1..8

槽位号就是 TCP 连接 ID(TCON_IP_v4.ID)。如果项目里别的通信已经在用这几个号(比如单任务版的 wConnId),要改 FB 里 INT_TO_WORD(#iSlot) 那一行,换成别的号段。

2. aBuf 默认 1000 个字

要处理更多,得把两处一起改大:VAR_IN_OUT 里的 ARRAY[0..999],以及段 1 体检和段 6 结果处理里的边界常数 1000 / 999。只改一处会越界。

3. 设备 ID 不是调用引脚

它是指令的静态变量 MB_Unit_ID(写在实例 DB 里),默认是 16#FF(255) —— 这是 MB_CLIENT 的出厂默认值,而 v3.2 及之前块里没写这个变量,报文里恒为 255,于是「采不回来」。

v3.3 起 DB100 每个从站多了 uUnitId:直连设备一般填 1;经网关挂 RTU 从站的填 RTU 站号(1..247)。

byVer 应为 16#08。

六、写的三条硬规矩

七、常见问题

wStatus = 16#80C8 / 16#80A4

接收超时 / 从站无响应。先 ping 从站 IP,再用 Modbus 调试工具单独连一次确认 502 端口通。从站 IP 必须和 CPU 同网段。

wStatus = 16#80C5

对端把 TCP 连接拒了或断了 —— 这是 TCP 层的事,跟 Modbus 协议和块逻辑无关。九成是这三样:① 从站 IP 或端口填错;② 对端根本没起 Modbus TCP 服务;③ 防火墙/网段挡着。

先在电脑上 ping 通 IP,再用调试工具单独连一次 502 端口;工具能连通了,再回来查块里的配置。

连得上,一发作业就断,报 80A1 / 8200 循环

两个都是连接层的码:80A1 = 连接被拒绝(本地端口或连接 ID 被占用);8200 = 这条连接正在处理另一个 Modbus 请求。

先确认 byVer 是不是 16#08 —— 不是就升到 v3.5。v3.4 及之前本块有两个时序缺陷会造出这个循环:拆连接只等两拍(10 ms 扫描才 20 ms,而 TCP 真实拆除要上百毫秒),以及连接参数每帧重写一遍(MB_CLIENT 每次都以为参数被改而要重新建连)。

设备 ID 在哪设?默认是 1 吗?

不是 1,默认 16#FF。临时验证:监视表把 FB52.astMB[1].MB_Unit_ID 强制成 1,读数马上回来就是它。


八、验证记录

配套仿真脚本用 Python 1:1 复刻了块的递推逻辑(同样的连接状态机、同样的任务轮转、同样的分片与落位规则),155 项断言全部通过:

配套的全局 DB 另有一份接口一致性校验脚本,逐项比对 DB 与 FB 的定义 (三个成员的数组上下限与元素类型、两个 UDT 的全部字段名、边界),27 项检查全部通过:

站上的规矩没变 —— 没跑通的不放上来。同批的其余几个块还在整理,没测完的我不往站上放。
使用与免责
源码按「现状」免费提供,仅供学习交流与合法用途。设备型号、模块版本、现场条件各不相同, 落地前还得对着厂家手册和图纸核实 —— 这里能帮少走弯路,不能替你签字。 用到项目上请自行验证,关键工况务必先在测试台上跑一遍。

这个块依赖西门子官方 MB_CLIENT 指令与相应版本授权, 部分场景需要 S7-1500 且 CPU 处于相应固件版本。用着有问题、或者想要什么功能,欢迎 来信。
← 自由口 Modbus RTU 从站 FB_ModbusRtuSlave 从站 FB_DiagOB 诊断三件套 ← 返回程序源码