简介:面向工业自动化现场调试与 PLC 编程人员,提供一份围绕三菱 FX5U 系列 PLC 与温湿度变送器实现 MODBUS RTU 通信的完整编程示例文档。内容覆盖 FX5U 485 串口通信参数配置、主站站号设置、温湿度变送器 A+、B- 接线,以及 GX Works3 中编写读取指令并将温湿度数据存入 D0、D1 的具体步骤,是快速掌握 MODBUS RTU 从站设备对接的实用参考。文档为单个 docx 文件,整体约 1018KB,以文字说明配合界面截图形式呈现,便于按步骤理解与复现程序调试流程。读者可借此熟悉 485 串口设置入口、通信参数与变送器手册的核对方法、MB 读取类指令的实际用法,也能明确温度与湿度寄存器地址的对应关系,减少现场联调时的盲目排查。已有 1030 人学习下载,适合作为三菱 FX5U 通信编程快速入门与现场常见排错对照的实用资料。 前阵子给车间做了一套环境在线监测的小改造,核心就是让三菱FX5U系列PLC通过MODBUS RTU协议,把分布在几个区域的温湿度变送器数据全部采集上来。这个活儿听起来不复杂,真正动手做的时候才发现,串口参数、报文格式、CRC校验、轮询时序、数据解析,每一个环节都有学问,官方手册写得又不够细,我踩了几个坑才算把整套逻辑跑稳。这篇就把完整的方案思路、编程示例和排错过程整理出来,给正在做FX5U串口通信的朋友做个参考。
我把这次项目的实践路径拆成五个部分:方案选型、硬件接线、协议分析、程序实现、故障排查。每一部分都是实际调试中必须跨过去的坎,少一个后面都会还债。
1. 通信方案选型与硬件准备
1.1 为什么最终选了MODBUS RTU,而不是模拟量信号
很多老工程师一提到温湿度采集,第一反应是4-20mA模拟量信号。模拟量方案在单点、近距离场景下确实简单直接,但这次项目的现场情况比较特殊:传感器分散在车间不同区域,最远的一台距离PLC控制柜将近120米,而且现场已经有几路485在用,新增传感器直接挂到现有总线上就行。
对比一下两种方案的差异就很明显:
| 对比维度 | 4-20mA模拟量 | MODBUS RTU |
|---|---|---|
| 布线成本 | 每台传感器需要一根三芯屏蔽线 | 一台变送器只需一根双绞线,可串联 |
| 扩展性 | 新增点位需重新放线 | 新增从站只需串进总线,改程序 |
| 传输距离 | 最远几十米,受干扰影响大 | 1200米内稳定可靠 |
| 工程量换算 | 需做4-20mA到工程量的线性换算 | 直接读寄存器,协议定了就是一比一 |
| 数据丰富度 | 只能传一个模拟量 | 温湿度、露点、自诊断信息都能传 |
再加上FX5U本体自带RS-485接口,MODBUS RTU主站功能是标配,不需要额外硬件成本。所以最后拍板就是用MODBUS RTU。
1.2 FX5U侧的硬件准备清单
FX5U系列PLC并不是所有型号的口都一样,先确认手头PLC的型号。FX5U本体上有一个RJ45以太网口,这是标配;串行通信口方面,大部分标准型FX5U带有RS-485通信口(端子式),部分紧凑型或者特殊型号可能需要加装FX5-485ADP通信扩展板。这块一定要先查手册确认,千万别想当然以为所有型号都有485口。
我自己用的是一台FX5U-80MT/ES,本体的RS-485口就是两线制的A+、B-端子排,接线直接压在端子上。调试阶段我还专门准备了一个USB转RS-485的适配器,方便先用电脑把变送器的通信参数摸清楚,再上PLC联调。
其他要准备的硬件:
- 带屏蔽层的双绞线(RVSP 2×0.75mm²起步,长距离建议1.0mm²以上)
- 120欧姆终端电阻两只
- 万用表和简易通断测试仪
- 如果是跨机柜布线,注意走线要避开变频器和动力电缆
1.3 变送器侧的资料确认,这个阶段最忌“猜”
拿到温湿度变送器,第一件事不是接线,而是翻手册确认几个关键参数:默认站号、默认波特率、数据位/停止位/校验方式、温湿度对应的寄存器地址、返回数据的数据格式。
我在这个环节就吃过亏。有一批变送器默认站号是1,波特率是9600,数据格式8N1;另一批默认站号是2,波特率却是19200,格式8E1。如果不看手册直接往PLC里配置,报文发过去对方根本不理会。
还有一点特别容易踩坑:寄存器地址体系。有些变送器手册写“温度寄存器地址40001”,有些写“协议地址0000”,这两种说法实际指向同一个地址。MODBUS报文里填写的起始地址是协议地址(0000对应40001的保持寄存器),如果不做换算,程序里地址经常会差1,导致读回来的数据驴唇不对马嘴。
2. 物理接线与从站参数设置,通信跑通前的关键准备
2.1 485接线细节,屏蔽层和拓扑结构都别糊弄
RS-485走的是差分信号,A和B两线决定逻辑电平,接线原则是A对A、B对B。三菱FX5U的485端子一般是A+(或标记为485A)和B-(或标记为485B),变送器侧通常也是A+、B-,按标识对接即可。
接线中最容易忽略的有三个点:
屏蔽层必须单端接地。很多项目现场把屏蔽层悬空或者两端都接地,悬空等于没屏蔽,两端接地会造成地环路,反而引入干扰。我一般习惯在PLC控制柜侧接地。
总线拓扑要手拉手串联,不能搞成星型。如果传感器分布是放射状,尽量在中间位置做转接,把总线串起来,不要让某台设备成为“T型分支的尾巴尖”,否则长线反射会让通信时好时坏。
终端电阻要接在总线物理两端。120欧终端电阻并联在A、B之间,但要注意——如果从站设备内置了偏置电阻或者终端电阻,就要计算总并联值,避免总线负载过重。有些国产变送器内部已经有120欧可选,拨码使能后外部就不用再并。
2.2 变送器的站号、波特率设置方法
站号设置方式各厂家差异很大:有的用拨码开关,有的用面板按键,有的只能通过通信参数写进去。拨码开关的一般是二进制编码,比如S1、S2、S3、S4四个拨码表示1~15站号,这个看说明书上的对照表设就行。
波特率、校验位的设置我强烈建议在接入总线前就与PLC侧对齐。默认值通常写在铭牌或快速手册上,但最保险的办法是先把单台设备接到USB转485适配器上,用电脑扫描一遍实际参数。
车间里几十台设备,如果站号重复,MODBUS总线上就会出现两台从站同时回复的冲突,表现为CRC校验永远不过、返回数据时对时错。排查起来相当头疼,所以布线前就要做一张站号分配表,登记清楚每台设备挂在哪个位置、站号是多少。
2.3 联调前先用串口调试助手做“预通信”
我不建议一上来就把变送器接到PLC上盲调。先做一轮电脑和变送器之间的通信验证,可以把问题范围缩小一半。
操作步骤很直接:USB转485适配器的A、B端接到变送器,电脑上打开Modbus Poll或者普通的串口调试助手,设好串口参数后手动发送一帧读命令,比如读1号站、功能码03、起始地址0、读2个寄存器,完整报文为:
01 03 00 00 00 02 C4 0B这帧报文里,01是从站地址,03是读保持寄存器功能码,0000是寄存器起始地址,0002是寄存器数量,C40B是CRC16校验值(低字节在前)。
如果变送器返回类似下面的数据:
01 03 04 01 2C 02 6E 7D A5说明通信链路、参数和地址都是对的,可以直接进行PLC联调了。如果这个环节就返回超时或者CRC错误,就不要带病上PLC,先排查是线的问题还是参数的问题。
3. 读懂MODBUS RTU报文与寄存器映射
3.1 RTU 数据帧结构,搞懂它才好定位问题
MODBUS RTU的报文结构非常规整,每一帧由四个部分组成:从站地址(1字节)、功能码(1字节)、数据段(N字节)、CRC16校验(2字节)。帧与帧之间需要有至少3.5个字符时间的静默间隔,这个间隔是RTU模式的硬性要求,用来分帧。
地址码的取值范围是1~247,0是广播地址。普通项目里从站地址尽量从1开始顺序排列,别把广播地址和保留地址卷进来。
功能码要分清使用场景:
| 功能码 | 含义 | 典型用途 |
|---|---|---|
| 0x03 | 读保持寄存器 | 读取可读可写的参数区 |
| 0x04 | 读输入寄存器 | 读取传感器实时测量值 |
| 0x06 | 写单个保持寄存器 | 设置单点参数 |
| 0x10 | 写多个保持寄存器 | 批量设置参数 |
温湿度变送器通常会把实时测量值放在输入寄存器区(功能码04),也有厂家放在保持寄存器区(功能码03)。两种我都遇到过,以手册为准,不要认死理。
3.2 温湿度变送器的寄存器地址与数据格式
最常见的标准映射关系是:协议地址0000存放温度,0001存放湿度。但不同厂家会做出差异化设计,例如有的把地址0放湿度、地址1放温度,有的会加一个地址2放露点温度,甚至有的设备自定义了浮点格式和整数格式切换寄存器。
数据格式这一块,普遍有四种情况:
- 无符号整型,实际值=读数值÷10(例如读回1325表示132.5℃或13.25℃)
- 有符号整型,温度零下时按补码计算
- IEEE754浮点数,占用2个寄存器共4字节
- BCD码表示,比较少见但仍在市场上存在
建议拿到变送器后先查手册确认格式,再用第2.3节的串口工具实测一组数据验算一遍,把协议约定吃透了再写程序。
3.3 CRC16校验的计算思路
如果使用GX Works3配合ADPRW指令做主站,CRC校验是PLC自动处理的,不需要写代码。但如果走无协议方式用RS/RS2指令收发,CRC就必须自己算。
MODBUS RTU的CRC16用的是IBM规范,生成多项式是0x8005,初始值为0xFFFF,结果低字节在前发送。计算逻辑是:每字节先异或到CRC低字节,然后右移8次,每移一次如果LSB为1就异或0xA001。给一段C语言参考实现:
uint16_t modbus_crc16(uint8_t *data, uint16_t len) { uint16_t crc = 0xFFFF; for (uint16_t i = 0; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x0001) crc = (crc >> 1) ^ 0xA001; else crc >>= 1; } } return (crc >> 8) | (crc << 8); // 低字节在前 }现场演示的时候用这个函数把样例报文算一遍,跟串口助手抓到的尾部CRC对比一致,说明理解到位了。
3.4 浮点型数据的字序陷阱
这次项目里用的是整数格式变送器,但我之前接过一批浮点格式仪表,差点载在字序上。
浮点数据4字节,被放在两个16位寄存器里。厂家协议如果按大端模式,那么寄存器地址小的放浮点的高16位,地址大的放低16位。而三菱PLC的数据寄存器对(比如D200和D201组合成32位数据)默认是低16位在D200、高16位在D201,正好反过来了。
处理方法很简单:先做一次字交换,再把数据作为浮点访问。用梯形图的话,可以用XCH指令交换D200和D201,然后把D200的32位数据MOV到浮点用寄存器,后续就能按浮点正常计算了。
4. 基于GX Works3的主站编程实现
4.1 通信参数配置,地址别写在两个地方
在GX Works3里,FX5U串口通信的参数配置位置在导航窗口的“参数—模块参数—RS-485端口”下,最核心的是把通信协议设置为MODBUS RTU模式,然后设置波特率、数据位、校验、停止位,必须和变送器完全一致。
这里有个容易混淆的细节:参数里设置的波特率和校验位是物理层的约定;而MODBUS从站地址并不在参数里设,而是在程序里通过ADPRW指令的实参指定。相当于参数决定“怎么说话”,指令决定“跟谁说”。第一次用的时候我把站号填到PLC参数的自站号里,结果指令里的地址一直配不对,调试了半天才反应过来。
PLC本体自身作为从站时的地址也在这个设置页面,如果现场还有触摸屏或上位机通过MODBUS读写PLC数据,要保证这个地址和总线上其他从站不冲突。
4.2 ADPRW指令格式与调用逻辑
FX5U在主站模式下读温湿度变送器,最直接的方式是调用ADPRW指令。指令格式是:
ADPRW S1 S2 S3 S4 D参数含义:
| 参数 | 含义 | 本例取值 |
|---|---|---|
| S1 | 从站地址 | K1(1号站) |
| S2 | 功能码 | H3(读保持寄存器)/ H4(读输入寄存器) |
| S3 | 起始协议地址 | H0(对应40001) |
| S4 | 寄存器数量 | K2(温度+湿度两个寄存器) |
| D | 数据存储首地址 | D200 |
实际梯形图里,我习惯这样组织:
- 用M0作为启动读取的触发,上升沿调用一次ADPRW,避免每个扫描周期连续发帧。
- 读取指令:ADPRW K1 H4 H0 K2 D200,温度结果放D200,湿度结果放D201。
- 执行完成标志用M8029判断,置位后做数据处理。
- 如果没有完成并且超时(我用T0定时50ms做超时判断),则置位错误标志,并复位触发条件准备重试。
ADPRW指令的好处是像黑盒子一样把报文组帧、CRC计算、超时重试都封装好了,程序里只要关注触发条件和结果判定即可。这一点对产线设备来说非常省心。
4.3 数据解析与工程量转换的梯形图实现
从变送器读回来的D200、D201是原始寄存器值,直接上位机用没有意义,必须先做工程量转换。
如果协议是整数除以10的格式,转换逻辑就是:
- 温度:D200 ÷ 10,得到一位小数的实际值
- 湿度:D201 ÷ 10,得到一位小数的实际值
考虑到温度可能为负,我建议用带符号除法。GX Works3的整数除法指令DIV支持32位数据,先把D200符号扩展成32位,再做除法,结果存到浮点寄存器供触摸屏显示。
梯形图粗略逻辑:
- 将D200 MOV到32位寄存器D300/D301(注意符号扩展)
- DIV D300 K10 D310,商在D310,余数在D311
- 把D310再转成浮点存入D320,后续直接用D320关联触摸屏
如果是浮点格式的变送器(比如读回D200、D201两个寄存器),在ST语言里转换就非常直观:
// 温湿度工程量转换(ST) IF bDataValid THEN // 整数模式:协议约定实际值 = 读数值 ÷ 10 fTemperature := INT_TO_REAL(D200) / 10.0; fHumidity := INT_TO_REAL(D201) / 10.0; END_IF;ST语言的优势在于数学计算可读性高,梯形图画浮点除法太占篇幅。实际项目里我常常是梯形图做逻辑控制和轮询,ST块做数值处理,两套语言配合使用。
4.4 多台变送器的轮询机制与超时处理
现场不止一台温湿度变送器的时候,单次ADPRW就不能满足需求了,需要做轮询。
我的实现思路是做一个简单的状态机:
- 状态0:向第1台变送器发ADPRW读请求
- 状态1:等待完成标志或超时标志
- 状态2:保存数据,切换下一台,回状态0
用计数器配合DECO译码指令或者直接做地址索引都行。这里要特别强调的是轮询节奏控制,很多新手在这里犯错误——一个扫描周期内连续对多台从站发请求,不管上一帧是否结束。485总线是半双工的,上一帧的应答还没回来就发新帧,必然导致总线冲突。
我通常在每台设备请求完成后插入至少20~50ms的间隔,让总线静默一段时间再发起下一帧。如果现场从站设备多,整个轮询周期可能需要几百毫秒到1秒,这对温湿度采集需求来说足够了,不必过分追求快。
超时时间设置也有讲究。设太短,从站稍微响应慢一点就误判超时;设太长,单台故障会拖慢整个轮询周期。我一般从50ms起步,实测不稳定再逐步加大,通常调到100ms能兼顾绝大部分情况。
多台设备轮询时,每台设备的通信状态最好单独记录。我把超时次数累计到D400开始的寄存器中,方便上位机统计哪台设备不稳定,这个在项目交付后的维护阶段非常有用。
5. 实测中的常见故障与稳定性调优
5.1 完全无响应的排错链路
联调阶段最让人抓狂的就是“指令触发了,但从站毫无反应”。遇到这种情况,不要急着改程序,按下面这个顺序排查:
先用USB转485适配器把变送器单独接电脑,手动发报文验证设备本身是否正常。这一步能把问题定位在“变送器或线路”还是“PLC配置”。
检查485接线:A/B是否接反。这是最基础的错误,而且不同厂家端子标识混乱,有的标D+、D-,有的标485A、485B,有的标A、B,很容易弄混。万用表量一下两台设备之间A对A、B对B的通断。
检查通信参数:波特率、数据位、校验位、停止位,逐项和变送器比对。我遇到过一台变送器拨码拨到了8N2,程序里是8N1,怎么发都没反应,用电脑扫描到实际参数才发现。
检查站号是否一致:PLC指令中的S1参数必须与实际变送器站号吻合,ADPRW里面写的K1代表1号站,变送器如果拨码是2,自然收不到。
检查PLC侧该通道的通信协议是否确实设置为MODBUS RTU模式,并检查PLC通信端口是否有报警位被触发。
按这个链路排查,绝大多数“完全无响应”都能在半个小时内找到根因。我自己的经验是,70%以上的问题出在A/B接反和参数不一致上,真正的硬件故障反而少见。
5.2 数据错乱的典型原因与处理
数据能回来说明链路通,但读回来的数值离谱,常见原因有这几种:
寄存器地址差一:变送器手册写“温度寄存器40001”,程序里起始地址却填了K1,实际应该填H0。这个属于MODBUS地址体系和PLC习惯性偏移导致的经典错误,把起始地址往0方向减1就好。
数据格式理解错误:变送器返回的是有符号整数,程序里却按无符号处理,零下温度会变成巨大正数。温度在冬季零下时必须检查符号位处理。
浮点字序颠倒:就是3.4节说的情况,读取到D200、D201后要先做字交换再用浮点方式解析。
高达“温湿度两只寄存器读反”:温度显示正常,湿度全乱,但数据范围看着又不是完全没道理。解决方案很简单:在Modbus Poll里手动读几个已知环境下的值,如果湿度和温度数值互换,那么程序里D200和D201的对应关系就错了。
我建议现场联调时,先在原地用校准过的温湿度计记录一组标准值,再对照PLC读回来的数据,这样判断数据错位和换算系数都非常直观。
5.3 偶发通信失败与485总线稳定性优化
设备平时工作正常,但时不时通信超时或数据错误,这类故障最磨人。现场排查经验告诉我,按以下顺序调优,大多数问题都能解决:
降低波特率:9600比19200抗干扰能力强很多。温湿度采集数据量小,9600完全够用,传输1帧只要几十毫秒,没必要为了那点速度牺牲稳定性。
改善线缆与接地:屏蔽层必须接,而且是单端接地。如果现场无法保证接地可靠,至少把屏蔽层接到控制柜的PE排上。
检查总线拓扑:手拉手串联是最理想的方式,星型分支处容易产生信号反射。如果实在无法改变布线,可以在分支处加中继器或者在主从两端都并终端电阻来吸收反射。
增大轮询间隔:给每台设备之间加间隔,降低总线占用率。尤其是和变频器、伺服驱动器在同一柜内时,设备启停瞬间的干扰很致命,让通信躲开这个时间段。
用“错峰”读取:如果总线上还有触摸屏或者其他主站,确认总线仲裁机制。多个主站同时发起通信会产生冲突,应错峰调度。
整套项目跑下来,我最深刻的体会是:MODBUS RTU这套通信方案就像单位里的老会计,规矩简单、可靠稳重,只要把默认参数、电平和布线的基本功做实,它能稳定跑很多年。最后再分享一个小技巧——现场如果温湿度数据偶尔跳变,可以在PLC里对连续两次读数做一次差值判断,超出合理范围就沿用上一次值,上位机显示会更平稳,用户感受也会好很多。
本文还有配套的精品资源,点击获取