一. 为什么搞这个东西
S7-200 SMART 做 Modbus RTU 主站,西门子官方的 MBUS_CTRL / MBUS_MSG 库功能上是够的,但真到项目里用,有几个地方很恼火:
- 每次都要配参数。读一个寄存器要调用一次 MBUS_MSG,参数从头写到尾,十几个从站下来全是重复劳动。
- 状态机自己手写。DONE 怎么接下一个、ERROR 怎么处理、超时怎么办,这些全得自己写逻辑。
- 多任务轮询头大。读不同的从站、读不同的寄存器、还要写数据,任务队列和调度逻辑光想想就烦。
- 故障恢复?不存在的。从站掉线就卡死,整个轮询停在那里等你超时,你不加额外的逻辑根本没法自动恢复。
所以搞了这个 S7-200-SMART-ModbusRTU-AutoPoll——一个基于任务表驱动的自动轮询子程序库。
核心思路
任务表驱动
所有通讯任务配置在 V 存储器的任务表里(最多 64 个任务)
子程序自动按顺序轮询,不需要你手动一个个调 MBUS_MSG库
单从站多任务、多从站混搭都支持
自动状态机
内置 8 个状态自动运行(IDLE → INIT → SCAN_TASK → BUILD_REQ → WAIT_DONE → PROCESS_RESP → NEXT_TASK → COMPLETE)
通讯握手、超时检测、故障跳过全自动处理. 你只管看输出状态,底层时序不用操心
离线管理
一个从站连续失败 3 次,自动标记为离线, 离线的从站不再发请求,快速跳过(< 1ms)
每 N 轮自动尝试恢复(默认 50 轮),从站恢复连接后自动恢复轮询
在线从站不受离线从站影响,保持正常轮询速度
配置灵活
任务参数通过 V 存储器数据块配置,支持 Excel 配置生成器自动生成数据块代码, 粘贴复制即可
支持寄存器读写(FC03/04/06/16)和线圈读写(FC01/02/05/15)
任务总数通过 VW1000 设置,数据块里直接进行修改
适用场景
单从站多变量采集 从一个从站读多个连续或不连续寄存器 温湿度传感器,10 个参数
多从站轮询 从多个从站轮着读数据 4 个变频器状态监控
混合读写 同时读写 读取温度 + 写入设定值
线圈控制 读写离散输出 阀门开关控制
二. 实战案例
案例 1:单从站读 10 个寄存器
需求:从从站 1 读 40001-40010(10 个保持寄存器)。
只需要在数据块中配置:
// 系统配置
VW1000 1 //任务数
// 任务 1
VB1004 1 // SlaveAddr = 1
VB1005 0 // RW = 0 (Read)
VD1006 40001 // ModbusAddr = 40001
VW1010 10 // Count = 10
VW1012 0 // DataOffset = 0
寄存器回传数据存在 VW2000-VW2018(10 个字)。
案例 2:混合读写
需求:2 个从站读,2 个从站写。
只需要在数据块中配置:
VW1000 4 //任务数
// 任务 1:从站 1 读 40001-40010
VB1004 1; VB1005 0; VD1006 40001; VW1010 10; VW1012 0
// 任务 2:从站 2 读 40001-40010
VB1020 2; VB1021 0; VD1022 40001; VW1026 10; VW1028 20
// 任务 3:从站 3 写 40001-40010
VB1036 3; VB1037 1; VD1038 40001; VW1042 10; VW1044 40
// 任务 4:从站 4 写 40001-40010
VB1052 4; VB1053 1; VD1054 40001; VW1058 10; VW1060 60
写入的数据预先填到缓冲区:VW2040-VW2058(从站 3)、VW2060-VW2078(从站 4)。
案例 3:寄存器和线圈混合
需求:单从站同时读写寄存器和线圈。
只需要在数据块中配置:
VW1000 4 //任务数
// 任务 1:读保持寄存器 40001-40002
VB1004 1; VB1005 0; VD1006 40001; VW1010 2; VW1012 0
// 任务 2:写保持寄存器 40003-40004
VB1020 1; VB1021 1; VD1022 40003; VW1026 2; VW1028 4
// 任务 3:读线圈 00001-00002
VB1036 1; VB1037 0; VD1038 1; VW1042 2; VW1044 8
// 任务 4:写线圈 00003-00004
VB1052 1; VB1053 1; VD1054 3; VW1058 2; VW1060 10
线圈数据格式:按位打包。VB2008 的 bit0=线圈1, bit1=线圈2。写入 VB2010 = 0x03 就是线圈3=ON, 线圈4=ON。
原文地址: 点击访问