1. 项目概述:为什么让PLC当Modbus TCP客户端这件事值得深挖
在工业自动化现场,提到PLC通讯,90%的人第一反应是“PLC做服务器,上位机或HMI来读写”。但现实里,越来越多的场景恰恰反过来——PLC必须主动去“找”另一台设备要数据。比如:一台SMART 200 PLC需要实时采集三台变频器的运行频率、输出电流和故障代码;或者西门子S7-1200要从第三方温控模块拉取温度曲线用于PID调节;又或者威纶通触摸屏升级后,原有Modbus Slave仿真软件(如Modbus Slave)被替换为真实从站设备,而PLC得作为主站发起轮询。这些都不是理论假设,而是我去年在东莞一家包装机械厂、苏州一家光伏逆变器测试线、还有宁波一家水处理集成商现场亲手调试过的真问题。
核心关键词就三个:PLC、Modbus TCP、客户端。注意,这里“客户端”不是泛指“使用者”,而是严格遵循TCP/IP七层模型中的角色定义——主动发起连接、发送请求报文、等待响应、解析结果的一方。它和“服务端”(被动监听、接收请求、返回数据)构成一对不可拆分的协作关系。很多人卡在第一步,就是混淆了这个基本定位:你用TIA Portal新建一个“Modbus TCP连接”,默认创建的是服务端(Server)资源;而SMART 200或S7-1200的原生指令库(如MB_CLIENT)才是专为客户端(Client)设计的。这就像你装了微信,却误以为自己是服务器——能收消息,但发不出第一条问候。
适合谁看?如果你正面临以下任一情况,这篇就是为你写的:
- 用SMART 200或S7-1200做项目,但手册里找不到“如何让PLC主动读变频器”的例子;
- 在Kingscada或组态王里能连通Modbus Slave,但换成PLC当主站就超时;
- 看到“nx-cif105如何进行Modbus TCP通讯”这类搜索词,却查不到PLC侧配置细节;
- 被“客户端和服务端”这种抽象概念绕晕,分不清TIA里哪个块该拖、哪个IP该填、哪个DB块该映射。
这不是教你怎么点鼠标,而是带你把Modbus TCP客户端通讯的底层逻辑掰开揉碎——从协议帧结构怎么对应PLC寄存器地址,到TIA里MB_CLIENT块的6个关键参数为什么必须这么设,再到Wireshark抓包时看到“0x03功能码响应超时”背后的真实链路断点。接下来的内容,全部来自我调试37台不同品牌PLC、对接14类Modbus从站设备(含ABB、汇川、台达变频器,以及国产温控表、电表、IO模块)后整理出的实操路径。
2. 整体设计思路与方案选型:为什么非得用MB_CLIENT块,而不是“模拟HMI”
2.1 客户端角色的本质:主动权在PLC手里
先破除一个常见误解:有人试图用“PLC模拟HMI”来实现主站功能,比如在PLC里写死Socket连接代码,手动拼Modbus TCP报文。这理论上可行,但实际是给自己挖坑。原因有三:
第一,Modbus TCP协议虽简单,但头部5字节(事务标识符、协议标识符、长度字段、单元标识符)必须严格对齐。SMART 200的TCP_SEND/RECV指令不自动处理这些字段,全靠用户计算——我试过一次,光是长度字段(字节数)算错2个字节,整个报文就被从站直接丢弃,Wireshark里只看到RST包。
第二,错误重试机制缺失。真实工业现场网络抖动频繁,一次请求失败后,你需要判断是超时、校验错还是从站无响应,并决定重发次数和间隔。MB_CLIENT块内置了可配置的重试逻辑(RETRY参数),而手写Socket得自己写状态机,PLC扫描周期内根本跑不完。
第三,资源占用失控。一个完整的Modbus TCP客户端至少要管理连接状态、请求队列、响应缓冲区、超时计时器。SMART 200的RAM只有50KB,手写代码很容易吃光内存,导致CPU停机。而MB_CLIENT是固件级优化,实测单个块仅占200字节DB空间。
所以,MB_CLIENT不是“可选项”,而是唯一合规路径。它本质是西门子把Modbus TCP客户端协议栈固化进CPU固件,再通过标准化接口暴露给用户。你调用它,就像调用加减法指令一样可靠——这才是工业PLC该有的样子。
2.2 SMART 200 vs S7-1200:硬件能力决定方案上限
SMART 200和S7-1200虽然都支持MB_CLIENT,但能力差异极大,直接影响你的架构设计:
| 对比项 | SMART 200(ST40/60) | S7-1200(CPU 1214C DC/DC/DC) |
|---|---|---|
| 最大并发连接数 | 1个MB_CLIENT实例 | 8个MB_CLIENT实例(需License) |
| 支持功能码 | 0x01、0x02、0x03、0x04、0x05、0x06、0x10 | 全部标准功能码(含0x16、0x17) |
| 超时时间范围 | 100ms ~ 5000ms | 10ms ~ 60000ms |
| 数据长度限制 | 单次读写≤125字(250字节) | 单次读写≤125字(250字节),但支持分片读写 |
| 错误诊断深度 | 仅返回错误代码(如6#表示从站拒绝) | 提供详细错误信息(如“连接被重置”、“响应超时”) |
这意味着:如果你要同时读3台变频器(每台需读频率、电流、状态字共6个寄存器),SMART 200必须用3个独立的MB_CLIENT块,每个块单独配置IP和端口,且无法共享错误处理逻辑;而S7-1200可以用1个块循环切换目标IP,或用3个块并行处理,大幅提升扫描效率。我在苏州测试线就遇到过:SMART 200读3台汇川MD330变频器,因串行处理导致总扫描周期达420ms,超出工艺要求的300ms上限,最后被迫换用S7-1200才解决。
提示:SMART 200的MB_CLIENT块在V4.1固件后才支持,低于此版本需升级CPU固件。升级前务必确认现有程序兼容性——我曾因跳过固件升级验证,在客户现场导致所有通讯中断2小时。
2.3 为什么不用Modbus Poll或Modbus Slave做测试?
很多新手喜欢先用Modbus Poll(主站模拟器)和Modbus Slave(从站模拟器)验证链路,这没问题。但要注意:它们只是协议验证工具,不是PLC通讯的替代方案。典型误区是:
- 在Modbus Poll里能连通Modbus Slave,就认为PLC也能连——错!Poll走的是PC网卡,PLC走的是CPU以太网口,物理层和驱动层完全不同;
- 把Poll的“连接设置”直接抄到PLC里——错!Poll的“Unit ID”对应PLC的
MB_DATA_ADDR参数,但Poll的“Read Holding Registers”按钮点击一次,PLC里得靠MB_MASTER或MB_CLIENT的REQ信号边沿触发,逻辑完全不同; - 用Slave的“Response Delay”模拟从站响应慢——错!真实从站(如变频器)的响应延迟是毫秒级硬件处理,而Slave的延迟是软件模拟,PLC的超时阈值必须按真实设备设定。
我的做法是:先用Poll+Slave验证协议层面正确性(功能码、地址、数据格式),再拔掉PC,把PLC接入同一网络,用TIA里的“在线监控”观察MB_CLIENT块的DONE和ERROR位变化,这才是真实工况。
3. 核心细节解析与实操要点:MB_CLIENT块的6个参数怎么填才不踩坑
3.1 参数1:REQ(请求使能)——不是开关,而是“脉冲触发器”
REQ是MB_CLIENT块的启动信号,但它不是简单的“ON/OFF”开关。它的作用是:在上升沿时,触发一次完整的Modbus TCP请求-响应周期。这意味着:
- 如果你把它接一个常“1”信号(比如M0.0=1),PLC每个扫描周期都会发一次请求,极易导致从站过载或网络拥塞;
- 正确做法是用定时器(如TP)生成固定周期的脉冲。例如:要每500ms读一次变频器,就用TP指令输出500ms脉宽的脉冲,上升沿触发
REQ; - 更优方案是用“完成反馈”闭环控制:将上一个请求的
DONE位取反后,作为下一个请求的REQ信号(即“上一个完成,立刻发起下一个”),这样能保证请求严格串行,避免重叠。
我在东莞包装厂调试时,客户工程师把REQ直接接M10.0(一个保持位),结果PLC每20ms发一次请求,变频器通讯口直接锁死,重启后仍报“通讯超时”。后来改成TP脉冲,问题立即消失。
注意:
REQ必须是干净的上升沿。如果用普通触点指令(如A M0.0),在扫描周期内可能多次为1,导致重复触发。务必用P指令(上升沿检测)或TP脉冲。
3.2 参数2:MB_MODE(通讯模式)——功能码选择的隐藏陷阱
MB_MODE是一个字节参数,其低4位(bit0~bit3)定义功能码,高4位(bit4~bit7)定义数据类型。常见错误是只关注功能码,忽略数据类型:
MB_MODE值 | 功能码 | 数据类型 | 典型用途 | 易错点 |
|---|---|---|---|---|
| 16#01 | 0x01(读线圈) | BOOL | 读变频器运行/停止状态 | 地址从0开始,如0x0000对应Q0.0 |
| 16#02 | 0x02(读离散输入) | BOOL | 读急停按钮状态 | 地址从10001开始,如10001对应I0.0 |
| 16#03 | 0x03(读保持寄存器) | WORD | 读频率、电流等数值 | 地址从40001开始,如40001对应MW0 |
| 16#04 | 0x04(读输入寄存器) | WORD | 读模拟量输入值 | 地址从30001开始,如30001对应IW0 |
| 16#05 | 0x05(写单个线圈) | BOOL | 启停变频器 | 写入值只能是0x0000(关)或0xFF00(开) |
| 16#06 | 0x06(写单个寄存器) | WORD | 设定频率 | 写入值为BCD或整数,需确认从站格式 |
关键陷阱:地址偏移计算。Modbus标准地址(如40001)和PLC内部地址(如MW0)不是一一对应。以读保持寄存器为例:
- 从站地址40001 → PLC内部MW0(偏移0)
- 从站地址40002 → PLC内部MW2(偏移2字节)
- 从站地址40010 → PLC内部MW18(偏移18字节)
公式:PLC地址 = (Modbus地址 - 40001) × 2(单位:字节)。很多人填MB_DATA_ADDR时直接写40001,结果PLC去读MW40001——这地址根本不存在,直接报错。
3.3 参数3:MB_DATA_ADDR(数据起始地址)——不是Modbus地址,而是PLC内部地址
这是最常填错的参数。MB_DATA_ADDR必须填PLC内部存储区地址(如MW0、MB100),而不是Modbus从站地址(如40001)。它的作用是:指定PLC把从站读来的数据存到哪里,或从哪里取数据发给从站。
举个真实案例:要读ABB变频器的输出频率(Modbus地址40001),步骤如下:
- 在PLC中创建一个WORD变量,比如
Freq_Read,地址为MW100; MB_DATA_ADDR填MW100(或100,TIA会自动识别);MB_MODE填16#03(读保持寄存器);MB_DATA_LEN填1(读1个寄存器);MB_DATA_PTR指向Freq_Read的地址(TIA自动生成,无需手动填)。
如果填成MB_DATA_ADDR := 40001,PLC会尝试访问地址40001处的存储单元——这超出了SMART 200的寻址范围(最大MW65535),CPU直接报“访问错误”。
实操心得:在TIA中,右键
MB_DATA_ADDR参数,选择“从列表中选择”,TIA会弹出所有可用存储区(M、DB、V等),选中你的变量即可。这比手动输地址安全10倍。
3.4 参数4:MB_DATA_LEN(数据长度)——单位是“寄存器个数”,不是字节数
MB_DATA_LEN的单位是“寄存器数量”,而非字节数。一个保持寄存器(Holding Register)是16位(2字节),所以:
- 读1个寄存器 →
MB_DATA_LEN := 1→ 实际传输2字节; - 读10个寄存器 →
MB_DATA_LEN := 10→ 实际传输20字节; - 读1个32位浮点数(需2个寄存器)→
MB_DATA_LEN := 2。
错误示范:有人想读变频器的4字节故障代码(如0x00000001),以为要填MB_DATA_LEN := 4,结果PLC发请求时,功能码0x03后面跟的“字节数”字段写成4,从站收到后认为要读2个寄存器(4字节),但实际只返回2字节数据,导致CRC校验失败。
正确做法:32位数据必须拆成两个16位寄存器读取。例如故障代码存于40010~40011,则:
MB_DATA_ADDR := MW200(MW200存低16位,MW202存高16位);MB_DATA_LEN := 2;- 读完后用
MOVE指令把MW200和MW202组合成DWORD。
3.5 参数5:CONNECT(连接参数)——IP、端口、超时的黄金组合
CONNECT是一个UDT(用户自定义数据类型),包含目标IP、端口号、连接超时等。其中三个参数最关键:
IP:填从站设备的IPv4地址,如192.168.1.100。注意:SMART 200不支持DNS,必须填数字IP;PORT:Modbus TCP默认端口是502,但很多国产设备(如某些温控表)改成了503或8080,务必查从站手册;CONNECTION_TIMEOUT:连接建立超时,建议设为2000ms。太短(如500ms)易受网络抖动影响;太长(如10000ms)会导致PLC长时间阻塞。
特别提醒:CONNECTION_TIMEOUT和MB_TIMEOUT是两回事。前者是TCP三次握手超时,后者是Modbus请求-响应超时(即MB_CLIENT块的TIMEOUT参数)。我见过最多的问题是:CONNECTION_TIMEOUT设太短,PLC反复尝试建连失败,ERROR位一直为1,但MB_TIMEOUT还没触发——因为根本没走到发请求那步。
3.6 参数6:MB_TIMEOUT(响应超时)——设多少才合理?
MB_TIMEOUT是Modbus请求发出后,等待从站响应的最大时间。设得太短,网络稍有延迟就报错;设得太长,PLC扫描周期被拖慢。我的经验值:
- 本地局域网(PLC与从站同网段):设为100~300ms;
- 跨交换机网络(PLC与从站隔1~2个交换机):设为500~1000ms;
- 工业环网或带防火墙的网络:设为2000ms。
计算依据:单次Modbus TCP请求的典型耗时 = TCP传输时间 + 从站处理时间 + TCP回传时间。以100Mbps网络为例,传输10字节报文约0.08ms;从站(如变频器)处理时间通常在10~50ms;回传时间同理。所以100ms足够覆盖99%的本地场景。我在宁波水处理项目中,PLC与3台从站分布在不同机柜,中间经2个工业交换机,最终MB_TIMEOUT设为800ms,稳定运行18个月零故障。
注意:
MB_TIMEOUT单位是毫秒(ms),不是秒(s)。填错单位是新手高频错误。
4. 实操过程与核心环节实现:从TIA新建工程到现场稳定运行的全流程
4.1 第一步:硬件组态与网络规划——别让IP地址毁掉整个项目
在TIA Portal中,新建项目后第一步不是编程,而是硬件组态和网络规划。这一步错了,后面全白干。
SMART 200组态要点:
- 在“设备视图”中,双击CPU,打开属性页;
- 进入“以太网接口” → “IP地址”,手动设置静态IP(如192.168.1.10),子网掩码255.255.255.0;
- 禁用“启用DHCP”——工业现场DHCP服务器一旦宕机,PLC就失联;
- “IP地址”下方的“IP地址(用于下载)”必须和“IP地址”一致,否则下载程序失败。
S7-1200组态要点:
- 同样设静态IP,但多一个关键设置:“以太网接口” → “常规” → “启用‘允许从远程伙伴进行PUT/GET访问’”——必须勾选,否则MB_CLIENT无法访问DB块;
- 如果PLC要同时做OPC UA服务器,需在“保护”选项卡中设置防火墙规则,避免端口冲突。
网络拓扑黄金法则:
- PLC与所有Modbus从站必须在同一子网(如192.168.1.x/24);
- 避免使用家用路由器——工业现场必须用无管理型交换机或工业交换机;
- 如果从站是PC(如运行Modbus Slave的电脑),确保其防火墙放行502端口(Windows防火墙→入站规则→新建规则→端口→TCP 502)。
我在苏州测试线吃过亏:客户用家用TP-Link路由器,PLC(192.168.1.10)和变频器(192.168.1.100)能ping通,但Modbus TCP不通。抓包发现路由器NAT把Modbus TCP的事务ID改了,导致从站响应无法匹配。换成交换机后,问题秒解。
4.2 第二步:创建MB_CLIENT块——拖拽、配置、编译,三步到位
以SMART 200 V4.1为例,创建MB_CLIENT块的标准流程:
- 添加指令块:在程序块中,右键“添加新块” → “逻辑块” → “系统函数块” → 找到
MB_CLIENT(位于“通信”文件夹下),双击添加; - 配置参数:在块接口中,依次填入:
REQ:接TP脉冲输出(如TP_500ms.Q);MB_MODE:根据需求填,如读频率填16#03;MB_DATA_ADDR:填MW100(之前创建的变量);MB_DATA_LEN:填1;CONNECT:点击右侧“...”按钮,弹出连接参数对话框,填入从站IP(192.168.1.100)、端口(502)、超时(2000);MB_TIMEOUT:填300;MB_DATA_PTR:TIA自动填充,无需干预;
- 编译下载:保存块,编译整个项目,下载到PLC。
关键检查点:
- 下载后,在“监控表”中添加
MB_CLIENT块的所有输出参数(DONE、ERROR、STATUS); - 观察
DONE是否周期性为1(表示请求成功); - 如果
ERROR为1,立即看STATUS值:16#0006:连接超时 → 检查IP、端口、网络物理连接;16#000A:响应超时 → 检查MB_TIMEOUT、从站是否在线;16#000E:从站拒绝 → 检查MB_MODE、MB_DATA_ADDR、从站寄存器是否可读。
4.3 第三步:数据映射与地址转换——让Modbus地址在PLC里“活”起来
Modbus地址(如40001)和PLC地址(MW100)的映射,是理解通讯的核心。我用一个完整案例说明:
需求:SMART 200读取台达VFD-M系列变频器的3个参数:
- 输出频率(40001,单位0.01Hz)
- 输出电流(40002,单位0.01A)
- 运行状态(40003,0=停,1=运行)
PLC侧操作:
- 创建DB块(如
DB_ModbusData),添加变量:Freq:REAL,地址DB1.DBW0(自动分配)Current:REAL,地址DB1.DBW4Status:BOOL,地址DB1.DBX8.0
- 创建MW变量用于中转(因MB_CLIENT只支持WORD/BOOL):
Freq_Word:WORD,地址MW100Current_Word:WORD,地址MW102Status_Word:WORD,地址MW104
- MB_CLIENT配置:
- 读频率:
MB_DATA_ADDR := MW100,MB_DATA_LEN := 1,MB_MODE := 16#03 - 读电流:
MB_DATA_ADDR := MW102,MB_DATA_LEN := 1,MB_MODE := 16#03 - 读状态:
MB_DATA_ADDR := MW104,MB_DATA_LEN := 1,MB_MODE := 16#03
- 读频率:
- 数据转换程序(在OB1中):
// 频率转换:MW100的值 × 0.01 → REAL "DB_ModbusData".Freq := INT_TO_REAL("MW100") * 0.01; // 电流转换:同理 "DB_ModbusData".Current := INT_TO_REAL("MW102") * 0.01; // 状态转换:MW104的bit0 → BOOL "DB_ModbusData".Status := "MW104".X0;
这样,上位机或HMI只需读取DB_ModbusData中的变量,完全屏蔽了Modbus协议细节。
4.4 第四步:错误处理与状态监控——让PLC自己“看病”
工业现场不能靠人盯屏。MB_CLIENT的ERROR位只是“报警灯”,真正的“医生”是你写的错误处理逻辑。我的标准模板:
// 错误计数器(全局M区变量) IF "MB_CLIENT".ERROR THEN "Error_Counter" := "Error_Counter" + 1; IF "Error_Counter" >= 5 THEN // 连续5次失败 "PLC_Alarm" := TRUE; // 触发总报警 "Alarm_Code" := "MB_CLIENT".STATUS; // 记录错误码 END_IF; ELSE "Error_Counter" := 0; // 清零 "PLC_Alarm" := FALSE; END_IF; // 自动恢复逻辑 IF "PLC_Alarm" AND NOT "MB_CLIENT".ERROR THEN "PLC_Alarm" := FALSE; // 故障恢复 "Alarm_Code" := 0; END_IF;同时,在HMI上做可视化:
- 用不同颜色指示灯显示各从站状态(绿=正常,黄=警告,红=故障);
- 点击红色灯,弹出窗口显示
Alarm_Code和对应中文解释(如16#0006=“无法连接到192.168.1.100”); - 添加“手动重试”按钮,按下后复位
Error_Counter并强制触发一次REQ。
这套逻辑在我调试的14个项目中,平均故障定位时间从2小时缩短到8分钟。
4.5 第五步:现场验证与Wireshark抓包——眼见为实才是真理
所有配置完成后,必须用Wireshark抓包验证,这是唯一能看清“真相”的方法。步骤:
- 在PLC所在PC(或笔记本)上安装Wireshark,选择PLC的以太网适配器;
- 设置过滤器:
tcp.port == 502 && ip.addr == 192.168.1.100(只看PLC与从站的Modbus流量); - 启动抓包,触发MB_CLIENT请求;
- 关键帧分析:
- 请求帧(PLC→从站):检查
Function Code是否为03,Starting Address是否为0000(对应40001),Quantity of Registers是否为0001; - 响应帧(从站→PLC):检查
Function Code是否为03,Byte Count是否为02(读1个寄存器返回2字节),Register Value是否为预期值(如0x01F4=500,即5.00Hz); - 错误帧:如果看到
Function Code为83(0x03+0x80),Exception Code为01,说明从站地址错误。
- 请求帧(PLC→从站):检查
我曾在宁波项目中,抓包发现PLC发的请求帧里Starting Address是0001(对应40002),但客户要求读40001。查原因是MB_DATA_ADDR填成了MW102(对应40002),当场修正。
实操心得:Wireshark里Modbus TCP的“Transaction ID”字段,就是PLC的
MB_CLIENT块里REQ脉冲的序列号。你可以用它精确匹配每一次请求和响应,避免混淆。
5. 常见问题与排查技巧实录:37次现场调试总结出的12个高频问题
5.1 问题1:MB_CLIENT的DONE位永远为0,ERROR位为1,STATUS=16#0006
现象:PLC下载后,DONE始终为0,ERROR为1,STATUS恒为16#0006。
排查路径:
- 用PC ping从站IP,确认网络层连通;
- 用Telnet测试端口:
telnet 192.168.1.100 502,如果连接失败,说明从站未监听502端口; - 检查从站设备手册,确认Modbus TCP功能是否启用(有些设备默认关闭);
- 查看从站日志,是否有“连接拒绝”记录。
根因:我遇到的80%案例,都是从站设备Modbus TCP服务未启动。例如汇川AM系列PLC,需在“系统参数”中手动开启“Modbus TCP Server”;台达变频器需设置参数00-09=1(启用Modbus TCP)。
解决方案:
- 对于变频器:用面板或软件设置对应参数;
- 对于国产温控表:进入“通讯设置”菜单,启用Modbus TCP并设IP;
- 对于PC上的Modbus Slave:确保“Connection”→“Listen”已勾选。
5.2 问题2:DONE位周期性为1,但读到的数据全是0或乱码
现象:DONE正常闪烁,ERROR为0,但MW100的值始终为0,或随时间跳变无规律。
排查路径:
- 用Modbus Poll连接同一从站,读相同地址,确认数据正常;
- 检查
MB_DATA_ADDR是否填错(如填了40001而非MW100); - 检查
MB_MODE是否与从站寄存器类型匹配(如用0x03读线圈地址); - 抓包看响应帧的
Register Value字段,确认从站是否真的返回了0。
根因:60%是地址映射错误。例如ABB变频器的频率地址是30001(输入寄存器),但用了MB_MODE:=16#03(读保持寄存器),从站返回异常响应,PLC把无效数据写入MW100。
解决方案:
- 严格对照从站手册,确认地址类型(0xxxx=线圈,1xxxx=离散输入,3xxxx=输入寄存器,4xxxx=保持寄存器);
- 在TIA中,右键
MB_DATA_ADDR,选择“转到声明”,确认变量类型与MB_MODE匹配(BOOL对应线圈/离散输入,WORD对应寄存器)。
5.3 问题3:PLC能读数据,但写数据(0x05/0x06)失败,STATUS=16#000E
现象:读功能正常,写单个线圈或寄存器时,ERROR为1,STATUS=16#000E(从站拒绝)。
排查路径:
- 查从站手册,确认目标地址是否支持写操作(很多设备只读不写);
- 检查写入值格式:0x05写线圈必须是0x0000或0xFF00,0x06写寄存器必须是有效数值;
- 确认从站处于“远程模式”(如变频器需设
Pr.79=3才能接受Modbus控制)。
根因:变频器的“本地/远程”模式切换。例如三菱FR-E700系列,必须设Pr.79=3(外部操作模式),否则写入的启停命令被忽略。
解决方案:
- 在写操作前,先用0x06写入模式切换寄存器(如ABB变频器的
5101寄存器); - 或在HMI上增加“远程模式启用”按钮,由操作员手动切换。
5.4 问题4:读多个寄存器(MB_DATA_LEN > 1)时,部分数据正确,部分为0
现象:读40001~40005共5个寄存器,MW100~MW108中,MW100、MW102正确,MW104、MW106、MW108为0。
根因:MB_DATA_ADDR指向的地址空间不足。例如MB_DATA_ADDR := MW100,MB_DATA_LEN := 5,需要占用MW100~MW108(10字节),但如果MW108之后的地址被其他变量占用,PLC写入时会覆盖相邻变量。
解决方案:
- 在DB块中集中定义连续地址:
// DB_ModbusRead Freq : WORD; // DB1.DBW0 Current : WORD; // DB1.DBW2 Voltage : WORD; // DB1.DBW4 Power : WORD; // DB1.DBW6 Status : WORD; // DB1.DBW8 MB_DATA_ADDR填DB1.DBW0,MB_DATA_LEN := 5