ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

汇川InoProShop串口自由协议实战:从通信帧设计到现场排错

2026/9/17 13:52:16 拓冰建站 浏览量
汇川InoProShop串口自由协议实战:从通信帧设计到现场排错 前阵子去客户现场调试一台第三方温控表对方的PLC已经定了但仪表只开放RS485串口协议还是厂家自定义的不是常见的Modbus RTU。我一听倒是松了口气——只要是串口能跑的协议汇川技术InoProShop里的串口自由协议基本都能啃下来。今天这篇就把InoProShop的串口自由协议从通信帧设计到轮询调度再到现场排错整个捋一遍希望能帮到正在跟各种“非标串口设备”死磕的朋友。说简单点串口自由协议就是PLC通过串口和外部设备通信时不按Modbus这类标准协议来而是完全按照对方设备手册里定义的数据帧格式去发送和接收数据。听起来很灵活但前提是你得搞清楚对方的通信协议格式自己拼帧、自己校验、自己解析。这个内容适合做设备集成、产线改造、非标自动化项目的电气工程师和PLC程序员尤其适合正在用InoProShop做汇川PLC开发又恰好遇到非标通信需求的同学。1. 自由协议和标准协议到底差在哪很多刚接触PLC通信的人有个误区觉得串口通信就是ModbusModbus就是串口。实际上Modbus只是串口通信协议里最通用的一种真正到现场会发现各种传感器、仪表、扫码枪、称重模块、变频器它们的通信协议五花八门。有的基于Modbus改几个功能码有的干脆完全自定义报文格式这时候就轮到自由协议上场了。1.1 自由协议和Modbus的区别Modbus RTU本质上也是一种“自由协议”的约定只不过它被广泛使用大家默认按它的帧格式来地址码、功能码、数据、CRC校验。而真正的自由协议则要求你完全遵从设备手册里规定的字节顺序和含义地址码可能是两字节功能码可能是某个固定命令字符串校验方式也可能是求和校验、异或校验、CRC16或者LRC更复杂一点的还会有应答超时重发机制。用一个不恰当的比喻Modbus是大家说普通话自由协议就是各地方言。讲普通话谁都会但门槛低遇到不会说普通话的人你必须学会对方的方言去交流。自由协议的价值就在这里——它让PLC能跟任何支持串口通信的设备对话前提是你愿意按照对方的规则去“说话”。在InoProShop里面标准Modbus通信只需要简单配置一下从站地址、寄存器地址和读写字数系统自动帮你构建报文帧。但自由协议模式下你不仅要自己规划发送缓冲区把每一个字节按顺序填进去还要处理接收缓冲区的解析逻辑校验算法要自己写超时时间要自己控制等于把整个串口通信的核心逻辑全部交到程序员手里。1.2 典型应用场景有哪些从我实际接触的项目来看自由协议最常出现在这几类设备上第一类是专用仪表和设备比如温控表、流量计、PH计、色谱仪、离子计等。很多仪表厂商都有自己的通信协议有的是简化版Modbus有的是纯ASCII字符协议比如发送“READ:001”这样的字符串来读取数据。用自由协议处理这类设备核心在于按手册拼字符串帧。第二类是工业上下游设备联动比如上位机、触摸屏或者视觉系统通过串口给PLC下发字符串指令。视觉系统最常见的做法就是输出一个字符串比如“OK”或者“NG:01”PLC收到后执行对应逻辑。这种情况用标准Modbus反而麻烦用自由协议最顺手。第三类是旧设备改造。很多老设备只有串口协议极不标准例如一个重量变送器可能用“STX数据ETX”这种带帧头帧尾的结构中间数据可能不是十六进制而是ASCII码组合。这类场景非得自由协议出马不可。1.3 InoProShop里自由协议的硬件通道在汇川技术InoProShop软件环境下自由协议通信通常是在H系列或H5U系列PLC上通过内置串口或扩展串口模块实现。具体硬件通道取决于你用的PLC型号和扩展模块但核心逻辑是一致的。以常见的H3U为例内置串口在自由协议模式下通信参数波特率、数据位、校验位、停止位需要在系统参数里先配置好。这里有个容易踩的坑很多人一开始设了自由协议但串口参数和对方设备不一致比如对方是偶校验你这边设成了无校验结果就是通信不稳定时好时坏。所以硬件通道选定之后第一步永远是对齐通信参数再去管报文内容。2. 通信帧设计与核心参数先懂原理再动手自由协议通信里最难的部分不是指令怎么用而是帧怎么设计、校验怎么算、缓冲区怎么规划。这部分搞不清楚通信就是玄学。2.1 一条通信帧的构成不管什么协议一条完整的串口通信帧通常由这几部分组成帧头标识一帧数据的开始常见的有固定字节如02H、0AH或者ASCII字符如“:”“$”地址码标识从站设备地址可能是1字节也可能是2字节ASCII码命令码/功能码表示要执行的操作比如读数据、写参数、校零等数据段要交互的核心数据长度不定校验码验证数据传输是否出错常见有CRC16、LRC、BCC异或校验等帧尾标识一帧数据结束常见有0DH、0AH回车换行或者0DH回车举个实际例子我之前调试过一台国产温控表它的读温度报文格式是这样的组成字节内容说明帧头0x3A “:”一个ASCII冒号地址0x30 0x31地址字符串“01”命令0x52 0x44“RD”表示读取数据0x54 0x31参数代码T1分隔符0x2C逗号结束0x0D回车这个报文实际发送的内容就是字符串:01RDT1,\r。如果用Modbus那套思路去套根本对不上。所以拿到设备手册第一件事就是画一个这样的帧格式表格把每个字节的含义、内容范围、是否固定值全部标出来再开始编程。2.2 CRC16校验手算与实现代码自由协议里最常见的校验方式是CRC16尤其是Modbus RTU协议衍生出来的各种变种基本都用CRC16。CRC16的计算原理不复杂但手算很容易错实际编程中直接用代码实现更可靠。Modbus RTU的CRC16算法可以概括为初始值为0xFFFF对每个字节先与CRC低字节异或再右移8次每次右移时如果最低位是1则与0xA001异或。计算完后CRC低字节在前发送。下面这个Python函数就是标准的Modbus CRC16计算我一般用它来验证PLC端计算结果是否正确def modbus_crc16(data: bytes) - int: crc 0xFFFF for byte in data: crc ^ byte for _ in range(8): if crc 0x0001: crc (crc 1) ^ 0xA001 else: crc 1 return crc # 以读保持寄存器报文 01 03 00 00 00 02 为例 frame bytes([0x01, 0x03, 0x00, 0x00, 0x00, 0x02]) crc modbus_crc16(frame) low crc 0xFF high (crc 8) 0xFF print(fCRC16 0x{crc:04X}, 发送顺序: 0x{low:02X} 0x{high:02X})运行结果是CRC160xC40B发送时低字节在前所以报文是01 03 00 00 00 02 0B 0C。你可以用这个结果去校验自己的计算逻辑对不对如果CRC计算不正确对方设备会把整帧丢掉表现出来就是“发是发了但对方不回应”这个坑特别容易踩。还有一种常见校验是LRC它在ASCII协议里用得多。计算方法是所有字节直接求和然后取反加一。比如对:01RDT1,\r中要计算的字节去掉帧头冒号、帧尾回车求和取低8位再取反加一就等于LRC值。LRC的计算量比CRC小很多但安全性也低一些适合通信距离短、干扰小的场合。2.3 缓冲区规划与通信参数选型自由协议通信不像Modbus那样有标准的寄存器映射发送什么、存到哪、接收什么、怎么解析全部需要你自己规划。我一般建议在PLC里划分专用的数据区来做缓冲不要直接散落在各个寄存器里。发送缓冲区建议固定200字节从D100开始接收缓冲区也固定200字节从D200开始。这样做的好处是程序逻辑清晰、变量地址固定调试时用监控表一眼就能看到发送和接收的原始字节。接收缓冲区的起始地址和长度通常在通信参数里绑定一旦设置好就不要在程序里乱改动。通信参数的选型遵循一个原则能低就不高。波特率9600虽然慢但抗干扰能力强传输距离远。现场有变频器、伺服这种强干扰源把波特率设到115200就是在找死除非通信数据量确实大否则9600才是稳妥的选择。数据位基本固定8位、停止位1位或者2位校验方式看对方设备手册要求偶校验最常用但也有设备要求无校验。3. 在InoProShop里把自由协议跑起来原理说得再多不如上手操作一次。下面我按一个完整的小项目来拆解用汇川PLC通过RS485串口读取一台第三方温控表的当前温度协议是厂家自定义ASCII格式波特率9600偶校验报文帧头为“:”帧尾为回车命令为“:01RDT1,\r”。3.1 硬件接线与参数配置第一步是接线。RS485是差分信号两根线分别叫A和B-这个接到温控表对应端子上。接线本身不难难点在现场环境。RS485的A/B线必须用双绞线或者屏蔽双绞线不要用普通平行电线。屏蔽层单端接地一般接在PLC侧的地线上。通信距离超过100米时末端要加120欧姆终端电阻这个电阻可以减少信号反射实测能明显降低偶发通信故障。接线完成后打开InoProShop的工程在系统参数里找到对应的串口配置界面。协议类型选择“自由协议”波特率设为9600数据位8位校验方式选择偶校验停止位1位。注意这些参数必须和温控表手册里的串口设置完全一致只要有一位不一致通信就会失败。串口参数配置好之后紧接着要定义通信缓冲区。InoProShop的自由协议通常需要指定发送缓冲区起始地址、接收缓冲区起始地址、允许接收的最大字节数。我的设置是发送缓冲区D100起始、接收缓冲区D200起始、最大接收长度200字节。这里要注意最大接收长度不要设得太小有些设备返回的数据里可能包含多个连续的帧设太小会丢数据。3.2 发送接收逻辑与轮询程序示例配置完成后核心工作就是编写发送接收逻辑。自由协议模式下程序逻辑可以归纳为这样一个状态循环置位发送请求、把要发送的帧按顺序填入发送缓冲区、触发发送、等待接收完成标志、解析接收缓冲区、处理数据。以温控表为例假设我们需要每秒读取一次温度。发送帧“:01RDT1,\r”在发送缓冲区里需要按ASCII码逐字节填入转换成十六进制就是frame_hex [0x3A, 0x30, 0x31, 0x52, 0x44, 0x54, 0x31, 0x2C, 0x0D]第一个0x3A是冒号“:”0x30 0x31是字符“01”0x52 0x44是“RD”0x54 0x31是“T1”0x2C是逗号0x0D是回车。有些协议帧尾是0x0D 0x0A回车换行这个要严格看手册多一个换行或少一个回车都可能被对方忽略。PLC端发送完成后等待温控表返回数据。返回帧一般也以冒号开头以回车结尾中间包含当前温度值比如返回“:01RDT1,235,\r”可能表示23.5度。解析时关键是定位温度数据的起始位置从接收缓冲区的起始地址开始先确认第一个字节是不是0x3A冒号然后逐字节找逗号0x2C的位置逗号后面的连续ASCII数字就是温度值。为了便于理解下面给出一段简化的流程伪代码实际在InoProShop里可以用ST语言或者梯形图实现// 定时触发每1秒置位发送请求 IF 定时发送 THEN 发送请求 : TRUE; END_IF // 发送子程序 IF 发送请求 THEN // 将帧头写入发送缓冲区首字节 发送缓冲区[0] : 0x3A; // : 发送缓冲区[1] : 0x30; // 0 发送缓冲区[2] : 0x31; // 1 ... // 写入帧尾后触发串口发送 启动发送(缓冲区首地址 : D100, 发送长度 : 9); 发送请求 : FALSE; END_IF // 接收解析检测到接收完成标志 IF 接收完成 THEN // 判断接收缓冲区首字节是否等于帧头 IF 接收缓冲区[0] 0x3A THEN // 查找逗号位置 索引 : 查找字符(接收缓冲区, 0x2C); // 从索引1开始解析ASCII数字 温度值 : 解析数值(接收缓冲区, 索引1); END_IF // 复位接收标志准备下次接收 接收完成 : FALSE; END_IF实际编程时InoProShop里有对应的串口发送和接收指令指令的具体名称和参数会因PLC型号和固件版本略有差异最简单的办法是参考当前固件版本对应的通信指令手册。核心逻辑就是上面这个结构理解了之后换成什么指令都不怕。3.3 联调测试步骤程序下载到PLC后先不要急着连温控表用串口调试助手做一次“假设备”测试。方法很简单把PLC的RS485串口通过USB转485模块接到电脑上打开串口助手设置同样的参数手工发送温控表的返回帧。这一步可以验证PLC接收解析逻辑是否正确也方便你直接观察PLC发送出来的内容是不是完全符合手册要求。测试无问题后再真正把RS485接到温控表上。切换成真实设备时要注意线缆没有接错、接线端子是否拧紧。很多人一上来就用真实设备联调一旦失败就很难判断是接线问题、参数问题还是程序问题用串口助手隔离变量能省很多时间。联调时推荐先发一条读命令观察返回数据。如果返回不了用表量一下RS485两根线之间有没有2-5V直流电压这个电压存在说明收发芯片在工作。一点电压都没有大概率是接线问题或串口参数配置没有生效。4. 常见问题和排错速查自由协议通信的报错表现就那么几种但原因可能千奇百怪。我把自己在项目里积累的排查经验整理成了一个速查表节省你在现场瞎折腾的时间。4.1 完全无响应的排查路线现象是PLC一直发送但设备一点反应没有。这种情况先不要怀疑程序逻辑按照下面的路线走一遍先确认硬件接线。用万用表量RS485的A和B之间是否有电压。正常工作时应该有两三伏的电压波动如果没有八成是接线松动或芯片没工作。再看看通信线是否接地正确RS485设备之间最好共地各设备的地线一定要连起来否则共模电压可能损坏通信。再确认串口参数。这里包括波特率、数据位、校验位、停止位每一个位都反复核对。我遇到过一台设备手册写的是波特率9600、偶校验结果实际出厂默认是19200、无校验害得我排查了半天。遇到这种情况优先用设备自带的调试软件测试通信确定设备实际参数后再改PLC程序。最后确认对方的通信地址。很多自由协议设备在报文里包含地址信息如果地址不对设备直接丢弃不响应。我曾因为仪表拨码地址和报文里填的地址不一致折腾了一晚上其实只要把地址改对就通了。4.2 数据乱码和错位的处理有时候通信能通但解析出来的数完全不对比如温度显示成几百万或者数值跳动特别夸张。这个问题多半是数据格式不匹配。考虑一种情况设备返回的是ASCII码“235”PLC程序却按照十六进制字节去解析。0x32 0x33 0x35这3个字节如果直接拼成一个十六进制数就是0x323335转成十进制是三百多万那数据怎么可能对。所以看到超大数、异常数第一反应就是检查数据解析方式ASCII字符要先减0x30再从高位到低位组合。还有一种是返回帧里包含几个连续的数据段比如温控表一次返回“:01RDT1,235,0,0,\r”里面有温度、报警状态、输出功率好几个值。解析时如果只按固定偏移找数据极容易错位。我建议先通过串口助手把一帧完整的返回报文打出来数清楚每个逗号在第几个字节位置再根据位置解析。不要只凭手册上的“大概位置”去写程序。4.3 超时反馈错误与ERROR CODE对照很多自由协议设备在收到错误指令时会返回一条固定的错误码这在调试时特别有用。常见的错误码含义如下表不同设备定义略有差异但大致逻辑相近错误码含义排查方向01非法功能码检查发送的命令码是否在设备手册允许范围内02非法数据地址检查参数代码、寄存器编号是否正确03非法数据值检查数据边界、字节长度是否合理04从站设备故障检查仪表本身状态、传感器是否异常FF未知错误检查报文帧格式、校验码计算遇到错误码反馈第一件事不是改PLC程序而是用串口助手直接向设备发送报文看看设备会不会返回相同的错误码。如果串口助手也返回错误码说明设备的协议逻辑没毛病问题在指令内容如果串口助手发送正常只有PLC发送出错那就是程序里填的字节或校验算错了。调试自由协议通信的时候还有一个容易忽略的细节很多设备要求两帧之间的间隔不能太短推荐在200毫秒以上。PLC如果毫不停歇地轮询发送设备会来不及处理导致数据拥堵。最粗暴的解决方法是把每次发送之间的间隔做成可调参数现场根据实际测试调整。4.4 从排错到上手的心得清单结合这么多年的经验我总结了一套做自由协议通信的固定流程每次上手都是这个套路第一拿到设备手册先画帧格式表不急着写程序。把帧头、地址、命令、数据、校验、帧尾逐项列出来标清每个字段是十六进制还是ASCII字符、是固定值还是变量。第二用串口助手模拟一次完整通信发一帧看一帧。只要设备能正常响应说明你已经掌握协议了后面的事情就是把这段交互逻辑移植到PLC里。第三程序里留好调试开关。我习惯在PLC里加一个“调试模式”位置ON时把当前发送帧和接收帧的原始字节全部搬到连续的寄存器里方便用监控表查看联调通过后再关闭。这样能省下大量翻手册核对字节的时间。第四通信不稳定的问题不要一上来就怀疑协议先排查现场干扰。变频器启动瞬间、伺服抱闸动作瞬间最容易出问题这些场合是不是该降波特率、加屏蔽层、区分电源地线优先级远高于调协议。如果这些路子都走了一遍还没搞定不妨把波特率往下降一档再看看。很多通信问题不是逻辑问题而是物理层问题。9600不行试4800高速通信在这种干扰大的现场确实比较吃亏降到稳定传输为止。我个人在实际操作中的体会是做自由协议通信耐住性子比技术能力更重要。把每一步分开验证把协议帧拆到最小单位去排错看起来慢实际上才是最省时间的方式。我见过太多人一次性把整个通信程序写完然后在现场抓瞎一个字节一个字节地猜问题那种煎熬我深有体会。记住一个原则先让一帧数据稳定跑通再去做整个通信轮询的架构设计。