Modbus TCP服务器功能块在NJ系列PLC中未周期性调用,是导致服务看似“配置完成却无法响应客户端请求”的最常见根本原因。这不是通信参数错误、IP冲突或防火墙拦截等外围问题,而是PLC程序执行机制层面的逻辑缺陷——功能块未被放入周期性任务中,等于从未被执行,其内部的监听套接字、连接管理、数据映射等初始化动作全部被跳过。
以下为完整、可立即执行的排查与修正指南。所有操作均基于NJ系列控制器(NJ-101, NJ-301, NJ-501等)及Sysmac Studio V1.46+环境,不依赖第三方库或额外硬件。
一、确认现象:区分“未启动”与“启动失败”
首先精准定位问题类型。打开Sysmac Studio → 连接目标NJ控制器 → 在“监视”视图中展开“任务”节点:
-
检查任务状态:
- 查看
MainTask(或你自定义的周期性任务,如ModbusTask)是否显示为 “运行中”。 - 若为“停止中”或“未启动”,说明任务本身未激活,功能块调用无从谈起。
- 查看
-
检查功能块实例状态:
- 在“变量监视”窗口中添加你声明的Modbus TCP服务器功能块变量(例如
MB_Server)。 - 展开该变量,观察其内部成员:
Status:应为0(OK);若为16#8001(Invalid configuration)或16#8002(Socket error),说明配置有误;IsRunning:必须为TRUE;若为FALSE,即表明功能块未执行或执行失败;ConnectedClients:正常运行时应显示当前连接数(0或正整数);若始终为0且IsRunning = FALSE,即锁定为“未调用”问题。
- 在“变量监视”窗口中添加你声明的Modbus TCP服务器功能块变量(例如
✅ 关键结论:
IsRunning = FALSE+Status = 0是本问题的黄金判据。它证明配置语法正确,但功能块从未进入执行流程。
二、根本原因:NJ PLC的任务调度机制
NJ系列采用确定性多任务架构。每个功能块(FB)不是“部署即运行”,而是必须被显式放置在某个周期性任务(Cyclic Task)的梯形图或结构化文本(ST)程序中,并由该任务按设定周期(如1ms、10ms、100ms)反复调用。
Modbus TCP服务器功能块(MBServer)是非自动启动型FB。它不注册后台服务,不监听系统事件,其全部行为完全依赖于你每次调用时传入的输入参数(Enable, IPAddr, Port, DataArea等)和内部状态保持。
若你仅做了以下操作:
- 在“变量”窗口声明
MB_Server : MBServer; - 在“配置”中设置了网络接口IP和子网掩码
→ 这不构成任何调用,MB_Server只是一段未执行的代码模板。
三、四步实操修正法(零容错)
步骤1:创建专用周期性任务(推荐100ms周期)
点击 “工程”窗格 → 右键“任务” → 选择 “新建任务”。
在弹出对话框中填写:
- 名称:
ModbusTask - 类型:
周期性 - 周期:
100 ms(Modbus TCP典型轮询间隔,兼顾实时性与CPU负载) - 优先级:
50(高于默认MainTask的40,确保及时响应)
点击 “确定”。
⚠️ 注意:不可使用
EventTask(事件任务)或FreeRunTask(自由运行任务)。MBServer必须在稳定周期内被调用,以维持TCP连接心跳与超时检测。
步骤2:将功能块实例放入新任务程序
双击 刚创建的 ModbusTask → 在打开的程序编辑器中:
- 若使用梯形图(LD):拖拽
MBServer功能块图标到网络中; - 若使用结构化文本(ST):输入以下代码(替换
MB_Server为你的实际变量名):
MB_Server(
Enable := TRUE,
IPAddr := '192.168.250.10', // NJ控制器自身IP(必须与Sysmac Studio中“控制器设置”一致)
Port := 502, // 标准Modbus TCP端口
DataArea := ADR(g_stModbusData), // 指向你的Modbus数据区结构体地址
MaxConnections := 16, // 允许最大客户端数(1~64)
Timeout_ms := 30000 // 连接空闲超时(毫秒)
);
🔍 数据区声明示例(在全局变量中):
g_stModbusData : STRUCT HoldingRegs : ARRAY[0..999] OF UINT; // 0x0000–0x03E7(1000个保持寄存器) InputRegs : ARRAY[0..255] OF UINT; // 0x0000–0x00FF(256个输入寄存器) Coils : ARRAY[0..1999] OF BOOL; // 0x0000–0x07CF(2000个线圈) DiscreteInputs : ARRAY[0..1999] OF BOOL; // 0x0000–0x07CF(2000个离散输入) END_STRUCT
步骤3:强制启用功能块(关键!)
MBServer 的 Enable 输入引脚是使能开关。它不是“启动一次”,而是每一周期都必须为 TRUE,否则功能块在该周期内直接跳过所有逻辑,IsRunning 立即变为 FALSE。
✅ 正确做法:
- 在
ModbusTask程序中,将Enable直接连接至常TRUE(LD中用“常开触点”接通,ST中写TRUE)。 - ❌ 错误做法:
- 用按钮变量控制
Enable(人为误关); - 用其他条件(如
SystemState = RUNNING)间接赋值(引入单次触发风险); - 遗漏
Enable连接(Sysmac Studio会报错,但新手常忽略)。
- 用按钮变量控制
步骤4:验证并固化启动逻辑
下载程序到NJ控制器(勾选“下载任务配置”和“下载程序”)。
点击 Sysmac Studio 工具栏“在线” → “开始在线监视”。
此时再次监视 MB_Server.IsRunning:
- 若 稳定显示
TRUE,且ConnectedClients在客户端连接后变为1,则修正成功; - 若仍为
FALSE,立即检查:
| 检查项 | 正确值 | 错误表现 | 解决方法 |
|---|---|---|---|
ModbusTask 是否启用 |
“运行中” | 灰色/停止中 | 右键任务 → “启用” |
IPAddr 字符串格式 |
'192.168.250.10'(带单引号) |
192.168.250.10(无引号)或 "192.168.250.10"(双引号) |
ST中必须用单引号包裹ASCII字符串 |
DataArea 地址有效性 |
ADR(...) 返回非零地址 |
ADR(...)=0 或编译警告 |
确认 g_stModbusData 已声明且不在局部作用域 |
| 控制器IP与PC是否同网段 | 例:NJ为 192.168.250.10,PC需设为 192.168.250.x |
PC为 192.168.1.x |
修改PC网卡IP或NJ的网络配置 |
四、进阶防护:启动自检与故障安全
为避免因程序重启、任务暂停导致服务静默中断,建议增加两层保障:
(1)上电自启动检测(ST代码,放入 ModbusTask 首行)
// 检测控制器重启后首次扫描
IF NOT g_bModbusInitDone THEN
// 强制重置功能块内部状态
MB_Server(Enable := FALSE); // 先关闭
MB_Server(Enable := TRUE); // 再开启
g_bModbusInitDone := TRUE;
END_IF
全局变量
g_bModbusInitDone : BOOL;初始值设为FALSE。
(2)运行时心跳监视(独立任务,1s周期)
创建 WatchdogTask(1000ms周期),加入以下逻辑:
// 若连续3次检测到 IsRunning=FALSE,则触发报警
IF MB_Server.IsRunning = FALSE THEN
g_uiWatchdogCounter := g_uiWatchdogCounter + 1;
ELSE
g_uiWatchdogCounter := 0;
END_IF
IF g_uiWatchdogCounter >= 3 THEN
// 写入诊断寄存器或触发HMI报警
g_stModbusData.HoldingRegs[999] := 16#ABCD; // 自定义错误码
END_IF
五、客户端验证:用标准工具确认服务活性
无需编程,用免费工具验证:
- 下载 Modbus Poll(Windows)或 QModMaster(Linux/macOS);
- 配置:
- Mode:
Modbus TCP - Connection:
IP = 192.168.250.10,Port = 502 - Read/Write:
Function = 03 (Read Holding Registers),Address = 0,Quantity = 10
- Mode:
- 点击 “Connect” → 若返回
0000至0009寄存器的当前值,则服务已100%激活。
💡 提示:若连接失败但
IsRunning = TRUE,问题已转移至网络层(交换机ACL、Windows防火墙、IP冲突),与本文逻辑无关。
六、常见误区与反模式(务必规避)
| 误区 | 后果 | 正解 |
|---|---|---|
将 MBServer 放入 MainTask 且周期设为 1ms |
CPU占用飙升,可能触发看门狗复位 | 用独立 ModbusTask,周期 ≥50ms |
使用 MBServer 的 Reset 输入引脚清零 |
仅清除连接统计,不重启服务 | Enable 置 FALSE 后再置 TRUE 才有效重启 |
在多个任务中重复调用同一 MBServer 实例 |
状态冲突,IsRunning 随机切换 |
每个 MBServer 实例仅由一个任务调用 |
| 认为“配置完网络接口就等于Modbus启动” | 完全误解NJ的执行模型 | 网络配置只是硬件准备,功能块调用才是软件启动 |
七、附:关键参数速查表
下表列出 MBServer 最常配置引脚的合法范围与典型值。所有参数必须在每次调用时稳定提供,不可为 UNDEFINED 或 NULL。
| 引脚名 | 数据类型 | 典型值 | 说明 |
|---|---|---|---|
Enable |
BOOL |
TRUE |
必须恒为 TRUE,否则功能块跳过执行 |
IPAddr |
STRING[15] |
'192.168.250.10' |
单引号包裹,长度≤15字符 |
Port |
UINT |
502 |
标准端口;若改用其他端口,客户端必须同步修改 |
DataArea |
POINTER TO ANY |
ADR(g_stModbusData) |
必须指向全局结构体,且结构体内存对齐正确 |
MaxConnections |
USINT |
16 |
范围 1..64;每连接约消耗2KB RAM |
Timeout_ms |
UDINT |
30000 |
范围 1000..600000(1秒至10分钟) |
⚠️ 注意:
DataArea结构体中的数组必须使用ARRAY[...] OF ...显式声明,不可用VAR_GLOBAL中的动态数组或指针间接访问。Sysmac Studio在编译时会校验该地址的静态可解析性。
八、终极验证清单(执行前逐项打钩)
- [ ]
ModbusTask已创建,周期设为100 ms,优先级50,且状态为“运行中” - [ ]
MB_Server实例已放置在ModbusTask程序中,Enable输入硬接TRUE - [ ]
IPAddr使用单引号包裹,且与NJ控制器实际IP完全一致 - [ ]
DataArea使用ADR(...)获取地址,且对应结构体已在全局变量中声明 - [ ] 下载程序时勾选了“下载任务配置”
- [ ] Sysmac Studio在线监视中
MB_Server.IsRunning显示TRUE并保持稳定 - [ ] Modbus Poll工具可成功读取
HoldingRegs[0]的值
完成以上全部,Modbus TCP服务器即进入可靠运行状态。

暂无评论,快来抢沙发吧!