ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

欧姆龙PLC通信协议精讲:FINS、Host Link与MODBUS-RTU踩坑实战

欧姆龙PLC通信协议精讲:FINS、Host Link与MODBUS-RTU踩坑实战 搞工控的兄弟应该都有同感欧姆龙PLC本身不难梯形图逻辑也直白真正让人血压飙升的永远是通信。我刚接触欧姆龙那会儿光“通信协议”这四个字就折磨了我好几个通宵。FINS、Host Link、MODBUS-RTU还有一堆端口号、节点号、网号、帧格式单看每个词都认识组合在一起就完全不知道从哪下手。更气人的是很多坑不是手册没写而是手册写了但我没看懂它在说什么。这篇东西就是我这些年跟欧姆龙PLC通信协议死磕之后沉淀下来的东西。把我踩过的坑、绕过的弯、最后搞明白的细节全部摊开讲。不管你是做上位机开发、触摸屏通讯、还是接仪表变频器只要你手里有欧姆龙PLC这篇文章应该能帮你省下不少白头发。1. 先分清欧姆龙的三种通信协议别一上来就抓瞎1.1 FINS、Host Link、MODBUS-RTU分别是什么欧姆龙PLC有三种我体感“日常使用率最高”的通信协议容易搞混但本质完全不同。第一个是FINS全称Factory Interface Network Service这是欧姆龙的“亲儿子”协议。它既可以跑在串口上也可以跑在以太网上专门用于欧姆龙设备之间、或者上位机与欧姆龙PLC之间的通信。只要你的画面里有“FINS UDP”、“FINS TCP”这类字眼就是在说这个协议。它的特点是报文结构统一从C系列到NJ/NX系列基本一脉相承学会一次换型号也不至于推翻重来。第二个是Host Link也叫上位机链接协议。这是欧姆龙老牌串口协议走RS-232C或RS-422/485用ASCII码文本帧通信。上位机发一条类似“00RD0000010002”的命令PLC返回一串ASCII文本人眼直接能看甚至可以用串口调试助手手搓命令来调试。缺点是功能相对基础速度也一般但在工业现场稳定性极佳早期很多触摸屏、组态软件跟欧姆龙PLC通信都是走它。第三个是MODBUS-RTU这不是欧姆龙发明的但欧姆龙PLC提供了非常成熟的支持。尤其当你需要跟第三方设备通信——温控表、变频器、电量表、流量计——MODBUS-RTU基本是绕不开的。欧姆龙PLC可以当主站主动去轮询从站也可以当从站被别人读。很多人不知道欧姆龙CP1H、CJ系列都内置了MODBUS-RTU简易主站功能不用自己一条条拼报文做工程非常省事。一段话总结我的理解FINS是欧姆龙设备之间的“官方语言”Host Link是串口时代的“通用语言”MODBUS-RTU是连接第三方设备的“国际普通话”。搞清楚自己当前场景该用哪个比急着看报文格式重要得多。1.2 选哪种协议先看你的硬件接口协议不是你想用哪个就用哪个硬件接口先要把你限制死。我用的比较多的是CP1H和CJ2M系列。CP1H自带USB编程口和一个内置RS-232C口还能扩展串口选件板CJ系列则是CPU单元上带外设口要想走以太网要么选带以太网口的CPU型号要么加一块以太网单元。你手里的物理接口直接决定了你能走什么协议。做个最简单的分类只有编程口想连电脑调试那默认走的是外设口通信一般选Host Link或者直接USB。有RS-232C/RS-485口要接仪表、变频器那就用MODBUS-RTU或者用Host Link做上位机连接。有以太网口要走上位机、触摸屏、多台PLC联网首选FINS UDP/TCP稳定性和效率都没得说。有个我早期犯的错误拿着只有串口的PLC非要跟组态软件走FINS TCP结果折腾半天发现硬件根本不支持最后老老实实加了一块以太网模块。所以做方案设计的时候第一个问题不是“用什么协议”而是“我有什么口”。1.3 通信的本质就是读写内存区别被各种名词吓住把协议都理一遍之后会发现不管FINS、Host Link还是MODBUS落到最底层干的事情其实就两件读PLC的内存区数据写PLC的内存区数据。PLC的逻辑程序跑起来之后温度、压力、产量、设备状态全部存在内存区里。通信协议做的事情无非就是按照约定好的格式把“我要读哪个地址、读多少个字”这条请求发过去对方再把“这些地址里存着什么”返回来。所以每个做通信的人第一件事就是要拿到一张地址映射表。这张表上写着CIO区对应哪些I/O点DM区对应哪些数据字WR区、HR区又是什么用途。FINS协议里管它们叫“内存区代码”MODBUS协议里管它们叫“寄存器地址”Host Link又称呼为“字地址”名字五花八门但本质都是同一个东西。我踩过的第一个大坑就是没把地址映射搞清楚。当时用MODBUS读一台温控表PLC里设从站地址设成了仪表说明书上的“通道号”结果怎么读都是0。后来翻遍手册才明白MODBUS从站地址和仪表内部的参数地址完全是两套编码体系中间差了一个“左移一位”的转换关系。从那以后我养成了一个习惯任何协议调试先把双方的地址映射表打印出来贴在屏幕上对照着填不要凭记忆。2. FINS协议拆解那些年让我懵圈的报文格式2.1 一个最简单的FINS读命令逐字节拆给你看FINS协议用起来不算难难点在于理解报文的每一段到底在表达什么。我拿一个最经典的例子来说上位机读PLC的D100开始的2个字。一条不含传输层头的FINS命令大概是这样的80 00 02 00 01 00 10 00 00 01 01 02 00 64 00 02别被这一串十六进制吓到拆开看其实很清楚80ICF控制标志位表示这是一个命令帧应答帧是C0开头。00RSV保留字节固定为0。02GCT网关计数一般直连就是2。00 01 00DNA是目标网络号DA1是目标节点号DA2是目标单元号。这块非常容易错后面细说。10 00 00SA1是源节点号SA2是源单元号SID是服务ID随意设一个就行用来匹配应答。后面这段才是正文01 01FINS命令码0101表示“内存区读取”0102表示“内存区写入”。02内存区代码02表示DM区82表示写DM区。00 64起始地址十六进制的0064就是十进制的100也就是D100。这里注意地址是用十六进制表示的不是BCD也不是ASCII文本。00 02读取的字数这里读2个字也就是D100和D101。如果正常PLC会回一条FINS应答大概长这样C0 00 02 00 01 00 10 00 00 01 01 00 00从第3个字节开始是返回的数据内容。看明白了这个最简单的读命令后面什么批量读、写数据、读时钟、控制运行停止套路都是一样的。2.2 节点号、网号、端口号连不上的头号元凶如果用FINS连接失败十有八九问题出在节点号、网络号、端口号这三兄弟身上。我早年用CX-Programmer连CJ2M填IP地址填的是192.168.0.5端口号默认9600理论上没问题可就是连不上。检查了一圈才发现以太网单元的“FINS节点号”不是1而是被拨码开关设成了5。上位机这边设置的“目标节点号”和PLC里实际的节点号对不上FINS协议直接就丢弃了这条报文。这里有个经验供参考欧姆龙PLC的FINS节点号一般有几种设置方式。有的型号在硬件上有旋转拨码开关直接拨到几就是几有的型号在PLC设置里可以手动指定还有的型号默认和IP地址的最后一位有关联。调试前千万别偷懒去PLC的以太网设置界面里看一眼实际值比在组态软件里瞎试快得多。端口号也有讲究。FINS标准端口是9600UDP和TCP都用这个。但有些上位机软件默认填的是其它值两边对不上数据包发过去了也石沉大海。另外一个常见坑是TCP和UDP的选择TCP有握手保证传输稳定UDP无连接速度快。如果走FINS TCP上位机要主动建立连接如果走UDP上位机不用握手发命令直接等应答就行但前提是两边的节点号、网络号已经对上。2.3 字节序和ASCII的恩怨情仇这个坑我栽了不止一次而且每次都栽得不冤因为只要没转过弯数据读回来就是错乱的。先说字节序。FINS报文里16位数据的表示方式是高字节在前、低字节在后。比如你要写一个十六进制的值0x1234到D100报文里的数据部分就是12 34不是34 12。大部分上位机开发都遵循这个大端序规则但总有些第三方设备、有些自己写脚本的兄弟习惯性地按照小端序处理结果读回来的数据完全对不上。再说ASCII问题。用串口助手调试FINS时千万别把十六进制数当成ASCII码去发。我就干过这种事在串口助手的发送框里输了个“0101”然后选了“按ASCII发送”实际上发送的是字符‘0’、‘1’、‘0’、‘1’对应的ASCII码0x30 0x31 0x30 0x31PLC收到之后直接判定非法命令。正确的做法是选“按Hex发送”才代表真正的十六进制报文。还有一个特别迷惑的地方Host Link协议因为本身是ASCII文本协议里面带的数据又是用ASCII表示的十六进制比如D100在Host Link里写成“0100”来回来去全是文本反而没有字节序的烦恼。这也是为什么老工程师调试串口时特别喜欢Host Link因为肉眼可读出错了拿串口助手一看就知道问题在哪。3. 实操用一台CP1H通过485读取温控表从零讲到通3.1 硬件连接与PLC通信参数设置纸上谈兵到此为止说一个我实际做过的一整套方案用CP1H的RS-232C口通过一个RS-232转RS-485的转换器接一台温控表PLC做MODBUS-RTU主站轮询读取温度值。这套配置在工业现场非常常见而且很有代表性。接线方面RS-485是两线制的A、B两根线不能接反接反了最直观的现象就是完全无响应。转换器这边要供电有些无源的转RS-485转换器不稳定尤其在环境干扰大的车间里数据帧经常损坏。我后来一律买带隔离的、有源供电的转换器虽然贵个几十块钱但省下排查的时间远超这个差价。PLC侧参数设置重点说几个位置在CX-PCX-Programmer的PLC设置里找到“串口1”通信模式选择“MODBUS-RTU主站”。波特率建议先从9600开始调确认通了再往上提。现场很多旧仪表最高只支持9600。数据格式一般选8位数据位、无校验或偶校验、1位停止位。第三方仪表手册会写清楚照抄就是。发送等待时间可以适当调大一些有些仪表响应慢PLC发完命令等200~300ms是常有的事。设置改完一定要“下载到PLC”并且让PLC重新上电设置才会真正生效。这个细节我吃了大亏。有一次改完设置直接在软件里监视以为生效了结果PLC里跑的通信参数还是旧的浪费了一个多小时。3.2 报文从哪里来地址映射、功能码与CRC校验在MODBUS-RTU这条链路里最需要花心思的就是“怎么把仪表的参数地址翻译成MODBUS报文”。拿温控表举例。假设表上有一组寄存器02地址是当前温度PV假设的例子里这样功能码是03读保持寄存器从站地址是1。要读这个参数主站发送的报文大概是01 03 00 02 00 01 25 CA拆开看01是从站地址03是功能码读保持寄存器00 02是寄存器起始地址00 01是读1个寄存器25 CA是CRC校验。这串报文最终要以十六进制的字节形式发送不是ASCII文本。这里最容易翻车的就是仪表手册上标注的地址和MODBUS报文里的寄存器地址之间的关系。我碰到的国产仪表有的手册直接写“MODBUS地址0201H”但实际往报文里填的时候需要左移一位有的则是“寄存器号3200”需要先转成十六进制再减1。每个厂家都不太一样拿到手册第一件事不是看功能说明而是先把通讯协议那章找到确认地址换算规则。CRC校验是MODBUS-RTU的另一个阴间细节。它的计算是对报文中从站地址到数据结束所有字节做CRC16多项式标准是0xA001结果低字节在前。举个例子上面那条报文的CRC部分25 CA计算出来的原始值是CA 25但发送顺序是低字节在前所以要写成25 CA。如果自己写上位机程序拼报文时稍微手一抖顺序写反了仪表那边直接不做任何响应。3.3 调试顺序怎么排才能不被坑调试MODBUS通信一定不要上来就写一堆PLC逻辑。我推荐一套效率极高的顺序第一步用串口助手先验证仪表的地址和CRC。把USB转RS-485接到仪表上手动发送上面那条报文如果能收到仪表回复说明从站侧没问题。这一步能帮你把协议问题从接线问题中剥离出来。第二步PLC不写程序先在PLC设置里确认模式然后用“PLC监视”看串口通信监视区的状态。欧姆龙PLC自带有通信状态字能看到本次通信是否成功比如D0里会有错误代码方便定位是不是参数设置问题。第三步再写程序。用欧姆龙官方提供的MODBUS功能块或者直接用TXD/RXD指令拼接报文把串口助手验证过的报文原封不动发送出去。只要能收到应答回读的数据再经过高低字节组合就能用了。这套顺序看起来啰嗦但能帮你把问题范围一刀切成小的。直接跳过第一步去调PLC遇到问题就分不清是仪表没回、还是PLC发出的报文有问题只能在原地打转。4. 常见问题与排查一条一条对着查4.1 高频问题速查表我把这些年遇到最多的通信问题整理成一张表遇到问题先对着查比上网搜半天强。现象可能原因排查思路PLC和上位机完全没通信IP地址不在同一网段先ping一下能通再查协议设置FINS TCP可以连上但UDP不通防火墙拦截UDP或节点号不对检查防火墙规则核对节点号映射MODBUS仪表偶尔正常偶尔超时485线太长、干扰大、接地不良换带屏蔽双绞线终端电阻匹配降低波特率MODBUS能收到仪表返回但数据明显不对字节序高低位对调或寄存器地址换算错了用串口助手抓原始报文对照手册逐字节分析Host Link发命令PLC不响应FCS校验算错或者命令字符没有转为ASCII用官方手册的FCS计算例子核对PLC从站模式别人读不了单元号从站地址设置错误在PLC设置里把单元号改成从站地址一致通信偶发失败复位通信又恢复节点号冲突两台设备用了同一个节点号把所有设备的FINS节点号改成唯一值CP1H串口设置改了没反应没有下载到PLC并断电重启把PLC设置下载到PLC重新上电这张表覆盖了我遇到的大部分问题场景。其中最有迷惑性的就是“偶发失败”因为不少工程师会怀疑自己的报文写得不对反复改程序实际却是节点号冲突这种低级问题。4.2 两个印象最深的坑节点号冲突和字节序错乱先讲节点号冲突。我第一次给设备加触摸屏时继电器柜里一台CP1H既要和触摸屏通信又要和上位机通信。触摸屏走的是FINS TCP上位机走的也是FINS TCP两台设备一开机都没问题运行一会儿就开始卡顿偶尔还掉线。查了很久最后发现触摸屏和上位机软件都把自己设成了同一个FINS节点号。FINS协议规定同一网络里节点号在通信时是唯一的。两个设备抢同一个节点号报文就会互相干扰。解决办法很简单给触摸屏和上位机各分配一个不同的节点号。这个坑我在其他项目里也遇过建议在做任何带多个上位设备的系统时先在方案里画一张“节点号分配表”从1到254排下去谁都不能重复。第二个典型坑是字节序错乱。有一次上位机读出来的温度值是“9640”实际显示却是12000多懵了好久才反应过来FINS报文里读回来的原始数据是25 80上位机按低字节在前拼成了0x8025而实际上欧姆龙PLC返回的是高字节在前应当是0x2580。这个坑其实不难避关键是新人容易忽视“数据在协议层怎么排”和“数据在应用程序层怎么解释”是两码事。4.3 用最简单的报文尽快验证通路很多兄弟在调试通信时一上来就写几十条指令、读几百个字结果报错都不知道错在哪。我的习惯是一切从最简单的单点读写开始。比如测试FINS通路就先读一个D区字比如读D0的1个字。报文短容易检查一眼就能看出是否通。通了之后再扩大到批量读。测试MODBUS也先读一个寄存器的1个数据比如仪表PV值通了之后再去读其它参数。这个顺序看着简单但背后是一个排查逻辑每一次只改变一个变量问题就永远是可定位的。如果第一次就去读一堆参数报文长、干扰多、寄存器地址错一个都查不出来那就成了大海捞针。另外强烈建议调试的时候打开串口调试助手或者Wireshark看一下到底是什么数据在线路上跑。上位机和PLC的连接抓一下网口包能看到FINS帧到底有没有发出来、发的什么内容。串口通信就挂个USB转485监听工具把PLC和仪表的通讯数据抓下来。很多时候你想象中“我发了这条报文”和实际上“你发了那条报文”差的还挺远。最后几个过来人的实在话说几句掏心窝子的经验。我做欧姆龙通信这几年最深的一个体会是不管是FINS、Host Link还是MODBUS调不通的大多数原因都不是协议高深而是低级细节没对上。地址映射表错一位、节点号冲突、CRC高低字节颠倒、串口参数不一致——这些坑没有什么技术含量但每一个都可能让你加班到深夜。所以我养成了一个习惯在每个通信项目开工之前先花半小时做三件事把双方地址映射表打印出来把节点号和端口号规划表写清楚把一条最简单的报文用串口助手提前验证通。这三件事做完后面全程基本就是按部就班地实现了。另一个建议是做上位机开发的朋友手里的抓包工具一定要顺手。Wireshark抓FINS TCP/UDP非常直观串口调试助手的Hex发送功能更是必备。调试时不要把时间花在“猜”上直接把报文抓出来对照手册问题大概率一眼就能揪出来。最后再送个锦囊欧姆龙不同系列的协议细节有时会有小差异比如CP1H和NJ在FINS区域的编码上略有不同。看手册时重点看命令码和内存区代码那几页用之前先在笔记里写下一个完整的报文例子后面照着改就行。通信这件事一旦通了第一条后面就都顺了。希望这篇踩坑记录能让你少走几段弯路。
返回列表