十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

汇川PLC串口自由协议实战:从接线到CRC校验的完整指南

汇川PLC串口自由协议实战:从接线到CRC校验的完整指南 产线上一台老型号的称重仪表通信接口只有RS485出厂说明书里没有Modbus就给你一张表格帧头是两个字节命令字对应读实时重量校验是CRC16数据是BCD码。这种设备怎么接进PLC答案就是串口自由协议。在汇川中型PLC的编程软件InoProShop里自由协议是一块绕不开的硬骨头说难不难但细节多文档又偏少很多新手第一次接触时容易卡在“数据明明发过去了为什么PLC收不到”“收到了怎么老是一堆乱码”这类问题上。这篇是系列教程的第四章前几章聊了InoProShop的环境搭建、PLC基础编程和I/O映射这次专门讲串口自由协议。我尽量不写那种照着帮助文档念的废话全是我实际调过的流程和踩过的坑硬件怎么接线、通信参数怎么匹配、报文帧怎么规划、InoProShop里的串口指令怎么用、程序怎么写才稳定以及收到错误数据怎么排查。适合刚接触汇川AM系列或类似Codesys风格PLC、同时对串口通信还不太熟的自动化工程师也适合设备维护人员在现场应急改程序时参考。1. 自由协议到底是什么先搞清楚它解决什么问题很多人一听到“自由协议”这几个字就发怵觉得没有“协议”两个字说得不踏实。实际上自由协议就是厂家或者用户自己定义的一套报文格式只要通信双方能看懂就行没有像Modbus那样固定的功能码、寄存器地址和校验规则。PLC发一串十六进制数据出去设备按自己的规则解析然后回一串数据给PLC。整个过程里报文里的每一个字节代表什么意思完全是双方约定好的。1.1 自由协议和Modbus的区别Modbus是标准协议它规定了报文里必须有从站地址、功能码、寄存器地址、数据长度、CRC校验格式是固定的。自由协议没有这些约束你可以把第一个字节定义成帧头也可以把第二个字节当命令字甚至可以在数据区里塞一段ASCII字符串全看设备厂家怎么设计。更直接的区别是Modbus是公开的、通用的PLC里面做好现成的功能块配置一下从站地址就能用自由协议则是“一机一议”的换个设备报文格式可能就完全不同程序也得跟着改。所以在InoProShop里前者有现成的Modbus库后者需要你用串口收发指令自己组装报文、自己做校验、自己解析数据。两者对比如下对比项Modbus自由协议报文格式标准固定有地址和功能码自定义按设备说明书定义编程难度低现成功能块直接调用高需自己组帧和解析通用性强绝大多数PLC和仪表支持弱仅适用于指定设备校验方式固定CRC16/RTU自定义校验或CRC16、求和校验适用场景标准仪表、变频器、电力监测老式设备、扫码枪、专用控制器1.2 为什么很多设备不能直接走Modbus我在现场碰到过很多莫名其妙的设备。有的仪表是国产小厂做的固件里只实现了一套私有RS485协议既不开放Modbus从站地址配置也没有文档告诉你功能码怎么映射有的扫码枪厂家默认透传模式数据过来就是一串以回车结尾的ASCII码根本不是标准通讯协议还有的称重仪表报文里带重量、带校验位、带状态标志偏偏就是不走Modbus。这种时候如果你只会在InoProShop里配Modbus那这活就没法干了。必须退回最底层用自由协议把这些设备“当做一个普通串口外设”来收发数据。这也是自由协议存在的最大价值它不依赖设备厂家实现什么标准只依赖双方对报文格式的约定覆盖范围反而比Modbus更广。1.3 自由协议的适用场景与限制自由协议最常见的应用场景有三个一是接老式计量仪表比如电子秤、流量计、地磅显示器二是接条码扫描枪、RFID读卡器这类具有串口透传功能的数据采集设备三是接一些非标定制的控制器比如自动化产线上某个专用工装的控制板。这些设备往往只有串口没有网口在重新布线不现实的情况下自由协议成了唯一选项。但自由协议也不是没有限制。它没有统一的差错重发机制报文出错需要你自己在PLC程序里做超时判断和重发处理另外自由协议一般也只能做一问一答的主从模式PLC主动发请求设备被动回数据想做设备主动上报的场合需要额外处理接收缓冲区和复杂的状态机。这些都是后面编程时要面对的。2. 动手前的硬件准备与通信参数匹配在InoProShop里写程序之前先把物理层搞定。很多新手上来就写代码代码写完了接上线发现死活不通最后排查了半天是接线的问题或者通信参数不对。串口通信这东西物理层不通软件写得再好也是白搭。2.1 接线方案RS232和RS485怎么选、怎么接汇川中型PLC的串口一般是COM口常见的物理接口有RS232和RS485两种。RS232是点对点通信速度一般不高距离短通常就是PLC和设备直接连RS485则是差分的抗干扰能力强距离可以到1000米以上还支持多点挂接工业现场用得最多。接线最容易犯的错就是A/B接反。RS485的A端对应设备的D/AB端对应D-/B接反了表现为完全不通或者偶尔能通但数据不稳定。我自己的习惯是上电之前用万用表量一下A、B之间的电压正常空闲状态应该在2V到6V之间如果量出来是0V左右八成是收发器没工作或者A/B接反了。RS232这边就比较简单三根线的事TXD接对方RXDRXD接对方TXDGND接GND。但要注意很多工控设备的DB9接口引脚定义并不是标准的有些设备的2脚是发送、3脚是接收有些则是反的接不通时先把2、3脚对调试一下。无论是RS232还是RS485都建议用屏蔽双绞线屏蔽层在PLC侧单端接地。长距离传输时RS485总线两端还要各接一个120欧的终端电阻否则信号反射会导致数据错乱。这些细节看起来不起眼但都是现场故障的高发点。2.2 通信参数怎么定波特率、数据位、校验位匹配原则串口通信双方的波特率、数据位、停止位、校验位必须完全一致否则收到的就是乱码或者根本收不到。设备的说明书里一般都会写清楚这些参数比如“96008N1”意思就是波特率9600bps、8个数据位、无校验、1个停止位。这里有一个需要特别说明的坑很多设备的串口参数是出厂默认的比如默认9600-8-N-1但你在PLC里改波特率很方便在设备面板上改参数反而麻烦。所以我的习惯是优先调整PLC侧通信参数去匹配设备而不是去改设备的默认参数。除非设备本身带拨码开关或菜单设置否则能不动设备就不动。在InoProShop里配置串口时波特率有2400、4800、9600、19200、38400、115200等可选。数据位一般选8校验位有无校验、偶校验、奇校验三种选择停止位大多是1位。要注意的是如果设备用了偶校验或奇校验那数据位8中实际上有1位是校验位有效数据是7位这个在报文解析时要特别注意否则数值可能错位。2.3 自由协议帧格式设计帧头、长度、命令字、校验穿插帧格式设计是整个自由协议通信的灵魂。设备说明书里一般会给出推荐格式比如常见的“帧头命令字数据长度数据区校验字”结构。如果设备说明书写得不清楚或者你是在和自制的单片机板卡通信建议按下面这种通用格式来定义字段字节数说明帧头11字节固定值如0xAA用于同步帧头21字节固定值如0x55进一步防止误识别命令字1字节0x01读、0x02写等数据长度1字节数据区的字节数数据区长度可变实际的数据内容校验字2字节可选求和校验或CRC16帧头设计得非常关键。只用一个帧头容易误判因为数据区里完全可能冒出一个和帧头相同的字节。我用两个不同的固定字节做帧头配合接收程序里的状态机判断误触发概率就低很多。数据区加上长度字段一方面方便接收程序判断这一帧什么时候结束另一方面也为数据解析提供了依据。2.4 校验方式的工程选择累加和还是CRC16自由协议里的校验方式没有硬性规定常见的有累加和校验和CRC16校验两种。累加和校验就是把一帧里所有字节加起来取低8位作为校验字节实现简单PLC里几行代码就能算完。但累加和校验对偶数位错误检测能力较差抗干扰性一般适合通信距离短、干扰小的场合。CRC16校验则要可靠得多。它基于多项式除法算法能够检测出绝大多数错误Modbus RTU协议用的就是CRC16。缺点是计算过程复杂一些尤其是如果你要在InoProShop里手写CRC16算法代码量会多一些但还好一次写好了后面所有自由协议通信都能复用。我的建议是设备说明书指定用哪种就用哪种如果自己定义协议通信距离超过几十米或者现场有大功率变频器优先上CRC16。3. InoProShop串口自由协议配置实操接下来是重头戏怎么在InoProShop里把自由协议跑起来。我先以一款常见的汇川AM系列中型PLC为例带大家走一遍完整流程。3.1 新建工程、添加串口设备节点进入InoProShop后新建工程选择PLC实际型号。在左侧设备树里找到CPU节点下面的“串口”或者“COM”节点添加一个串口设备。这一步不同版本的软件界面可能略有差异但大方向一致。添加完串口设备后双击打开配置界面把波特率、数据位、停止位、校验位等参数填进去。这里的参数要和目标设备匹配这是我前面强调过的。注意InoProShop里可能会有一个“通信超时”或者“响应超时”的配置项表示PLC发送请求后等待响应的最长时间默认值可能偏小如果现场设备响应慢这里需要调大。另外很多汇川中型PLC的串口节点下面还会有一个RTS/CTS或者485方向控制的设置。用RS485时最好确认一下收发方向控制是自动的还是由程序控制的如果是自动模式那收发切换交给硬件处理程序里不用额外操心如果是手动模式就得在程序里控制方向引脚这个要特别留意不然会出现“发得出去收不回来”的怪现象。3.2 串口打开与参数写入SComm_Open使用InoProShop里串口通信库提供了几个SComm开头的功能块常用的有SComm_Open打开串口、SComm_SendTo发送数据、SComm_RecvFrom接收数据、SComm_Close关闭串口。使用自由协议的第一步是打开串口。在梯形图或者ST里调用SComm_Open填上串口号和通信参数。比如用ST语言大致是这样// 声明变量 fbOpen : SComm_Open; bOpenDone : BOOL; bOpenError : BOOL; wErrorCode : WORD; // 主程序中调用 fbOpen.Com : 1; // COM1口 fbOpen.BaudRate : 9600; // 波特率 fbOpen.DataBits : 8; // 数据位 fbOpen.Parity : 0; // 0无校验1奇校验2偶校验 fbOpen.StopBits : 1; // 停止位 fbOpen(bExecute : TRUE, bDone bOpenDone, bError bOpenError, wErrorID wErrorCode);SComm_Open执行后必须确认bDone为TRUE才说明串口打开成功。如果bError为TRUE要查看wErrorCode对应的错误码常见的错误是串口被占用或者参数非法。串口在程序里打开一次就够了不要每次发送都要打开一次再关闭一次那样效率低还容易出错。3.3 发送与接收指令详解SComm_SendTo、SComm_RecvFrom串口打开之后发送数据用SComm_SendTo接收数据用SComm_RecvFrom。这两个指令配合起来就是一个完整的一问一答通信周期。SComm_SendTo负责把一帧数据发出去。调用时你要传入一个发送缓冲区数组、数据长度这些参数。发送完成标志位为TRUE后才能进行下一步。注意这里是先发数据发完之后立即转入接收等待状态。SComm_RecvFrom负责从接收缓冲区里读数据。调用时它会返回是否收到了数据、缓冲区里有多少字节、具体的数据内容。自由协议里SComm_RecvFrom通常不是一次调用就能读完整帧数据因为串口数据是按字节到达的PLC循环扫描周期和设备的发送时间不一定同步所以接收逻辑一般要写成“先收到一个字节就算有数然后持续读取直到凑齐一帧”。接收这一部分新手最容易犯的错就是在主程序里写一个SComm_RecvFrom指望它一次调用就能把设备回的所有数据都收齐。实际调试时你会看到有时候数据没到齐就读走了有时候读出来的数据中间缺了几个字节。正确的处理方法是轮询接收只要接收缓冲区里有数据就持续读进来直到收到的字节数达到帧长度再统一解析。3.4 一个完整的轮询收发示例含CRC代码下面给一套可以直接参考的ST语言示例。假设设备协议是帧头0xAA 0x55命令字0x01表示读取重量数据长度固定为2字节数据区CRC16校验低字节在前、高字节在后。第一步先封装CRC16计算函数。在InoProShop里新建POU用结构化文本写FUNCTION_BLOCK FB_CRC16 VAR_INPUT DataIn : ARRAY[0..255] OF BYTE; Len : UINT; END_VAR VAR_OUTPUT Crc : WORD; END_VAR VAR i : UINT; j : INT; Temp : WORD; END_VAR Crc : 16#FFFF; FOR i : 0 TO Len - 1 DO Crc : Crc XOR DataIn[i]; FOR j : 0 TO 7 DO IF (Crc AND 16#0001) 0 THEN Crc : (Crc SHR 1) XOR 16#A001; ELSE Crc : Crc SHR 1; END_IF; END_FOR; END_FOR;这是Modbus标准CRC16算法InoProShop里支持FOR循环和位运算直接复制就能用。多项式0xA001是CRC16的常见变体判断一下设备说明书里的校验字节顺序有的设备是低字节在前有的是高字节在前对应调整发送顺序。第二步在主程序中组帧发送。用一个定时器触发生成发送触发信号然后把请求帧填到缓冲区里// 发送请求帧 IF bSendTrigger THEN SendBuf[0] : 16#AA; // 帧头1 SendBuf[1] : 16#55; // 帧头2 SendBuf[2] : 16#01; // 命令字读取 SendBuf[3] : 16#02; // 数据区长度 SendBuf[4] : 16#00; // 数据区内容 SendBuf[5] : 16#1E; // 数据区内容 // 计算CRC作用于SendBuf[0]到SendBuf[5] fbCRC16(DataIn : SendBuf, Len : 6); SendBuf[6] : fbCRC16.Crc AND 16#FF; // CRC低字节 SendBuf[7] : (fbCRC16.Crc SHR 8) AND 16#FF; // CRC高字节 fbSendTo(bExecute : TRUE, Data : SendBuf, DataLen : 8); END_IF;第三步接收处理。用一个状态机控制发送完请求帧后进入接收等待状态每次扫描周期调用SComm_RecvFrom读取接收缓冲区当缓冲区里已经有了完整帧长度的数据校验CRC通过后再按协议解析出实际数值。这里有一个调试心得接收解析时不要只等一次调用要循环读缓冲区直到所有期望字节都到位否则极易出现帧丢失。4. 常见问题与排查技巧实录串口自由协议这东西遇到问题时如果没思路很可能折腾半天找不到方向。我把这几年调试中遇到最多的问题整理了一下按硬件层和软件层来分类方便大家现场快速定位。4.1 硬件层485不通信、A/B反接、终端电阻如果PLC发了数据但设备完全没反应先不要急着看程序重点检查物理连接。第一确认A/B有没有接反。很多设备说明书里的标识不一定统一有的叫A/B有的叫D/D-有的叫485/485-。用万用表量空闲电压是最快的方法。第二检查共地问题。RS485是差分信号虽然理论上不需要共地但实际环境中如果两个设备的地电位差太大超过收发器的共模电压范围通信就会异常。这时候需要把两个设备的GND连接起来。第三检查终端电阻。如果通信线路超过几十米且两端没有接120欧终端电阻高速率下波形反射严重可能导致数据误码。但要注意终端电阻只接在总线两端如果只是两三个设备短线连接不接也能工作。第四确认RS485收发方向控制是否正常。有些PLC的串口模块需要程序控制收发切换方向方向没切换过来就会出现“发送的时候正常接收的时候总线一直被发送端占用”的问题。4.2 软件层串口打开失败、收不到数据、接收帧错位串口打开失败最常见的原因是程序里重复打开同一个串口或者串口被其他功能块占用。InoProShop里有些应用场景下Modbus和自由协议共用同一个串口如果你同时启用了Modbus从站功能和自由协议收发串口就会被冲突占用表现为SComm_Open报错。解决办法是确认同一个串口同一时间只被一种功能使用。收不到数据时先用串口调试助手代替设备看看PLC发的数据出来是不是对的。如果PLC发的字节和设备说明书不一致问题出在组帧如果PLC发的数据是对的但设备还是不应答可能是设备侧没有设置成正确的从站地址或者设备本身要求应答前有延时。接收帧错位是很隐蔽的一个坑。设备回的数据是“AA 55 01 02 12 34 56 78”这样的完整帧但SComm_RecvFrom每次可能只读到两三个字节如果你在程序里直接把收到的字节按固定偏移去解析就会得到错误的数据。解决方法是先定义一个接收缓冲数组把每次读到的字节追加进去然后判断缓冲数组的长度是否达到整帧长度达到后再做帧头和校验字的确认。4.3 经验速查表现象可能原因排查/解决措施完全无响应A/B接反、参数不匹配、设备电源异常万用表量电压核对波特率参数收到乱码波特率或校验位不一致查看设备说明书配对参数时通时不通线路过长、干扰、地电位差换屏蔽线、接终端电阻、连接GND打开串口失败串口被占用、重复打开检查是否有其他功能块占用相同的COM口接收帧错位接收数据未凑齐整帧调整接收逻辑按帧头长度确认整帧数据偶发错误校验缺失或干扰强加CRC16校验重发机制收发方向异常RS485方向控制配置错误检查InoProShop串口节点方向控制设置这套排查路径我用了很多年基本能覆盖自由协议通信中九成以上的问题。还有一个通用建议是在正式调试PLC之前先用USB转485模块加串口调试助手把设备完整调试一遍确认波特率、报文格式、校验收发都正确后再对接PLC。这样能把“设备问题”和“PLC程序问题”隔离开省掉大量现场排查时间。5. 自由协议的工程经验补充程序结构设计写到最后还有一个工程层面的经验想多说几句。5.1 组帧、发送、接收、解析四大模块单独封装自由协议一旦要对接多台设备程序结构就非常重要。很多工程师习惯把所有逻辑写在一个POU里刚开始看着简单等接入第二台、第三台设备时整个程序就变得没法维护。建议把协议处理拆成四个功能块组帧、发送、接收、解析每个功能块只做一件事。组帧功能块负责根据命令字和数据生成完整发送帧内部调用CRC16计算发送功能块负责串口发送指令封装接收功能块负责从缓冲区累积数据并判断是否收到完整帧解析功能块负责把接收到的字节按协议转成实际工程值。这样以后换设备只需要改组帧和解析两个功能块发送和接收功能块完全复用。5.2 轮询多设备通信的状态机设计如果一条总线上挂了多台设备比如三台秤PLC需要依次读取每台的数据这时建议用状态机轮询状态0读取1号秤等待响应收到响应后切换到状态1读取2号秤等待响应以此类推循环。每个状态下都要有独立的超时判断超过设定时间没收到响应就跳过当前设备去读下一台避免因为某一台故障导致整个总线卡死。这个状态机看起来简单但实际工程里特别管用。我以前接过一个项目一条485总线上挂了8台显示仪表就是靠这套轮询状态机稳定跑了好几年。刚开始也有人图省事每台设备单独发一条指令然后用延时等待结果整个扫描周期被拉得很长后来改成轮询状态机问题全解决了。5.3 调试时多做“数据快照”InoProShop在线监控有一个很方便的功能可以监控数组变量的每一个元素。调试自由协议程序时把发送缓冲区和接收缓冲区数组都拖到监控列表里程序运行时就一目了然发送缓冲区的字节对不对接收缓冲区里有没有数据第几个字节不符合预期。我见过不少同事调试时只盯着接收到的数值变量看发现不对又不知道错在哪其实只要看一眼接收缓冲区原始字节问题立刻就清楚了。我个人在实际操作中的体会是串口自由协议在InoProShop里并不难难的是把通信前的准备工作做好硬接线可靠、参数匹配准确、报文格式设计合理。前面这些工作花足了功夫写PLC程序其实就是一个组帧和解析的体力活。最后再分享一个小技巧现场调试时随身带一个USB转RS485模块串口调试助手配好参数先单独确认设备报文再对接PLC至少能帮你省下两个小时的无头绪排查时间。
返回列表