尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

InoProShop串口自由协议详解:从配置到CRC校验的完整实战指南

InoProShop串口自由协议详解:从配置到CRC校验的完整实战指南 做自动化这些年被问得最多的不是指令怎么写而是串口自由协议到底是个啥、怎么用。尤其汇川的InoProShop一打开软件界面串口配置里躺着自由协议四个字很多新工程师就卡在这了。这篇是InoProShop入门系列的第四章前几章聊了软件安装、基础指令和程序结构这一章单独把串口自由协议掰开揉碎讲清楚。我尽量用项目里真实遇到的场景来说你在现场踩过的坑基本都在这篇里了。1. 自由协议不神秘先说清楚它解决什么问题1.1 所谓自由是相对于标准协议而言的串口通信本身只负责一件事把一个字节一个字节的数据从A设备搬到B设备。至于这些字节代表什么、什么顺序发、发完等不等应答通信双方得自己商量好这套商量好的规则就是协议。像Modbus RTU、Modbus ASCII、PLC Link这些属于标准协议。标准协议的好处是规则公开PLC里直接有现成指令从站地址、功能码、寄存器地址往那一填就能通。但坏处也明显——协议格式是固定的设备厂商若不想按这套规则来你就没辙。自由协议也叫无协议通信就是把规则的决定权交给你。PLC的串口不按任何预设的帧结构收发你想发01 03 00 00 00 01也行想发A5 5A 00 10 FF也行只要对端设备认这套格式。InoProShop里所谓的自由协议模式本质就是把串口从标准协议引擎切换为裸收发通道。1.2 什么场景非用自由协议不可我自己的项目里遇到这几类设备基本就得切自由协议设备类型常见通讯格式为什么不能直接用Modbus条码扫码枪ASCII文本帧以回车换行结尾扫码枪是被动输出不是标准的寄存器读写模型地磅仪表STX命令数据ETX校验和厂商私有帧结构命令字是字符型的RSDW这类温控器/温湿度变送器自定义十六进制帧寄存器地址和功能码映射不透明没法套标准模型老式变频器厂商私有ASCII协议出厂只支持自己的协议你只能去适配它拿扫码枪举例最直观。现场一台扫描枪读取条码后主动往串口发一串ASCII字符以\r\n结尾你根本不知道也不需要知道它内部是什么寄存器。这时候用Modbus反而无从下手自由协议就一个字收。收完自己解析。反过来也要说一句如果设备本身支持Modbus或者你只是去读几个寄存器优先用Modbus RTU。自由协议虽然灵活但帧解析、校验、超时处理全得自己写出错概率和维护成本都高不少。选型原则很简单——能用标准协议就别折腾自由协议被逼到墙角了再上。1.3 这篇文章你会得到什么我把串口自由协议的完整链路拆成四步配置串口参数 → 发送数据 → 接收数据 → 解析校验。下面每一节对应一个环节最后用一个地磅仪表的实际案例串起来再补一段踩坑实录。你看完不一定能成为协议专家但至少回到现场碰到这个仪表要用自由协议读数据的需求知道该从哪下手。2. InoProShop里的串口配置第一步错后面全错2.1 先分清楚你用的是H3U还是H5UInoProShop这个软件同时支持汇川H3U和H5U两代PLC但这两代在串口配置上差别很大很多人在这栽跟头。H3U属于传统型PLC编程思路和日系PLC一脉相承。它的串口通信参数虽然最终落在特殊寄存器里但InoProShop提供了图形化配置界面。你在左侧工程树里找到PLC参数或串口配置点开COM1或COM2协议选无协议或自由协议软件版本不同叫法略有差异波特率、数据位、校验位、停止位在下拉框里选好即可。软件会自动换算成D8120COM1或对应的特殊寄存器值。H5U则是基于CODESYS内核的IEC 61131-3平台配置在设备树里完成。展开设备树找到H5U控制器下的串口节点双击打开属性页同样把波特率这些参数填好通信模式选自由协议。H5U没有直接暴露特殊寄存器参数直接烧录进系统配置里。2.2 通信参数每一项都不能随便填配置界面上那几个参数看起来简单实际上每一处都可能是通讯失败的导火索参数常见取值踩坑提醒波特率9600、19200、115200两端必须完全一致差一点都不行。现场经常有仪表出厂默认9600你按115200配怎么调都不通数据位8绝大多数设备是8位7位在老式ASCII设备上偶尔见一般碰不到校验位None、Even、Odd这是最容易被忽略的。很多设备默认偶校验你用了无校验收上来的数据就是乱码还查不出原因停止位1、2默认1位就够除非对端设备手册明确要求2位我的习惯是拿到一台新设备第一件事不是接PLC而是先翻设备说明书里串口通信参数那几页把波特率、校验位记在便利贴上。参数确认之前不要动程序。2.3 自由协议模式下哪些配置是无效的还有一个细节当你把串口切换成自由协议模式后类似从站地址站号这类参数就失效了。因为站号是标准协议的东西自由协议没有站的概念就是一问一答或者被动收发。有些工程师习惯性在配置界面里填了站号1发现不通信然后去怀疑站号填错了——实际上它根本不影响自由协议的数据收发别在这上面浪费时间。3. 收发逻辑RS指令和功能块两条路殊途同归3.1 H3U的RS指令老规矩指令块标志位H3U的自由协议收发核心是RS指令。它的格式是RS [发送缓冲首地址] [发送字节数] [接收缓冲首地址] [接收缓冲最大字节数]举个实际例子RS D200 K8 D300 K50意思是从D200开始取8个字节发出去接收缓冲区从D300开始最多收50个字节。注意串口是字节操作但D寄存器是16位的所以每个D寄存器只用低8位存一个字节发8个字节就是D200到D207。配合RS指令的还有几个特殊标志软元件作用使用要点M8122发送请求置ON后启动发送发送完成自动复位M8123接收完成标志收到一帧数据后置ON处理完必须手动复位D8123已接收字节数M8123为ON时这个寄存器存着本次实际收到的字节数D8129接收超时设定串口收完最后一个字节后超过该时间没再收到数据就认为一帧接收完成程序的套路很固定。发送时先在程序里往D200~D207填入要发的数据然后置位M8122。接收时M8123一旦为ON马上读D8123得到字节数从D300开始挨个取数据解析解析完成后复位M8123让PLC进入下一轮接收。这里有个关键点M8123不复位就再也收不到下一帧数据。很多新手通讯只通一次第二次就没反应了十有八九是忘了复位M8123。3.2 H5U的COM功能块打开→发送→接收三步走H5U的串口自由协议走的是功能块路线思路比RS指令更直白先用COM_Open之类的功能块打开串口拿到通信句柄再用这个句柄去发送和接收。以ST语言为例伪代码长这样// 打开串口 COM_Open( Port : 1, // COM1 BaudRate : 9600, DataBits : 8, Parity : COM_NONE, StopBits : 1, Handle hCom1 // 输出句柄 ); // 发送8字节请求帧 COM_Send( Handle : hCom1, Data : ADR(sendBuf), // 发送缓冲区首地址 Length : 8, Done sendDone, Error sendErr ); // 接收数据超时200ms COM_Recv( Handle : hCom1, Data : ADR(recvBuf), Length : 50, Timeout : 200, Done recvDone, Length recvLen, Error recvErr );功能块的具体名字不同版本的InoProShop指令库里可能略有出入你打开软件的指令树搜COM或者串口就能找到当前版本对应的块。但调用逻辑是稳定的打开串口只为一次发送是触发式的接收靠超时判断一帧是否结束。H5U和H3U最核心的差别在于H3U的接收完成由硬件自动判断帧结束H5U则是你给一个超时时间在设定的时间内没等到新字节就认为帧收完了。这个Timeout参数要配得符合设备实际发送节奏给太短容易把一帧拆成两半给太长又拖慢通讯周期。3.3 接收超时背后的原理你必须懂不管是H3U的D8129还是H5U的Timeout本质都是帧间隔超时的判断机制。它假设一台设备在发送一帧数据时字节与字节之间的间隔是稳定的、短促的而一帧结束到下帧开始之间间隔相对较长。于是PLC利用这个时间差收到第一个字节后开始计时每个新字节到来就重置计时器直到超过设定阈值没新字节进来就宣布这帧收完了。理解了这点你就知道超时时间该怎么设——设备发送一帧数据内部字节间最长间隔要小于你的超时阈值设备两帧之间的最短间隔要大于你的超时阈值。对于大多数仪表和扫码设备把超时设在10ms到50ms之间基本够用具体可以实测后微调。4. 完整案例用自由协议读取地磅仪表重量4.1 先把设备的协议文档吃透案例我用最常见的数字地磅仪表来演示这类设备在配料、称重、仓储项目里出镜率非常高。假设仪表说明书上写的工作协议如下读取稳定重量上位机发送命令帧02 52 53 03 35 44仪表应答帧结构02 44 57 [符号] [6位重量ASCII码] [小数位] 03 [校验和]逐字节拆开看字节含义02STX起始符44 57ASCII字符DW表示稳定重量符号2B或2D-ASCII的加号/减号6位重量数字的ASCII码比如012345表示12345小数位0~4表示重量数据里从右往左第几位是小数点03ETX结束符校验和前面所有字节的累加和取低8位用ASCII十六进制两个字符表示收到这么一帧比如02 44 57 2B 30 31 32 33 34 35 01 03 39 45解析出来就是正数、重量012345、1位小数即12345.5kg。最后校验和字节39 45是ASCII的9E也就是前面字节累加和的低8位。4.2 发送请求帧的程序实现H3U这边梯形图思路就是先把请求帧塞进D200~D205然后置位M8122D200 16#02D201 16#52RD202 16#53SD203 16#03D204 16#35D205 16#44然后SET M8122数据就发出去。这里要注意RS指令发送字节数是6不是8因为帧就6个字节。H5U的ST代码更灵活直接用数组初始化发送缓冲区VAR sendBuf : ARRAY [0..5] OF BYTE : [16#02, 16#52, 16#53, 16#03, 16#35, 16#44]; recvBuf : ARRAY [0..49] OF BYTE; recvLen : UINT; hCom1 : DWORD; sendDone, recvDone, sendErr, recvErr : BOOL; END_VAR发送完成后进入接收等待。H5U里用一个状态机控制比较优雅空闲态发命令、等待态收应答、解析态处理数据每200ms一轮循环。4.3 收上来的数据怎么变成重量值不管用哪款PLC收到原始字节后都要自己做解析。我习惯写一个专门的解析函数输入接收缓冲区首地址和数据长度输出重量值。核心步骤校验帧头是否为02帧尾是否为03不对就丢掉验证校验和把帧头到ETX之间的所有字节累加低8位和校验和比较从缓冲区的固定偏移位置取出符号位和6位数字ASCII码转成数字根据小数位字节把整数除以对应的10的幂次得到实际重量。以H5U的ST函数为例截取关键片段// 假设recvBuf里是一整帧recvLen是实际长度 // 校验通过后执行这段 weight : 0; FOR i : 0 TO 5 DO ch : recvBuf[4 i]; // 跳过 02 44 57 符号位 digit : ch - 16#30; // ASCII转数字 weight : weight * 10 digit; END_FOR decimal : recvBuf[10] - 16#30; // 小数位 FOR i : 1 TO decimal DO weight : weight / 10; END_FOR IF recvBuf[3] 16#2D THEN // 负号 weight : -weight; END_IF;这里面我踩过的坑是偏移量算错。每个设备协议里字段位置不一样写解析代码前先从串口助手里抓一帧真实数据把每个字节对着协议文档标一遍再动手。纸上标错了程序里必然错。5. 校验与容错CRC16和异常帧处理是通讯的灵魂5.1 为什么说校验比通讯本身更重要很多入门工程师觉得数据能收到就万事大吉校验是多余的。这是大忌。工业现场有变频器、电机、接触器这些强干扰源串口线上出现一个字节的跳变太常见了。如果整个通讯链路不上校验重量值偶尔跳变一次配料系统可能就是一批废料。自由协议里的校验方式取决于对端设备的协议文档。有的设备用累加和Sum Check像上面地磅仪表例子有的用CRC16Modbus RTU也用的是CRC16。无论哪种PLC侧必须原样实现算法参数多项式、初值、结果异或值要对上。5.2 CRC16-Modbus的ST实现CRC16-Modbus在汇川PLC里很常用我贴一份在InoProShop里验证过的ST代码FUNCTION CRC16_MODBUS : WORD VAR_INPUT pData : POINTER TO BYTE; len : UINT; END_VAR VAR i : UINT; j : UINT; crc : WORD : 16#FFFF; END_VAR FOR i : 0 TO len - 1 DO crc : crc XOR WORD(pData[i]); FOR j : 0 TO 7 DO IF (crc AND 16#0001) 16#0001 THEN crc : SHR(crc, 1) XOR 16#A001; ELSE crc : SHR(crc, 1); END_IF; END_FOR; END_FOR; CRC16_MODBUS : crc;调用时把待校验的缓冲区首地址和长度传进去返回的就是CRC16-Modbus结果。注意Modbus协议里CRC是低字节在前发送的如果你的设备协议要求高字节在前发送前需要把高低字节交换一下。这一点不确认清楚校验永远是失败的。5.3 超时、粘帧、断帧三种现场最常见的异常通讯异常不用怕关键是有没有处理策略。我把它们归成三类超时命令发出后设备一直不应答。代码里必须有一个超时计时器比如500ms没等到应答要置一个通讯故障标志并重新发命令或上报故障。千万不要让程序卡死在无限等待里。粘帧设备发出的两帧数据黏在一起到达或者PLC一次读到了两帧内容。解决办法是解析时按帧头、帧尾找完整帧从缓冲区里抠出一帧来剩余字节保留等下一轮拼接。H3U的RS指令每次接收是独立覆盖的所以最好在M8123为ON后立刻把数据搬到自己的全局缓冲区再处理。断帧一帧数据因为干扰被拆成两段到达超时判断会在第一段结束时误认为帧结束了。应对方法是在解析逻辑里做长度判断收到的不满足最小帧长直接丢弃等待下一帧。不要因为收到数据了就高兴不完整的数据和没收到是一样的。6. 实战排坑记录乱码、丢字节、偶发通讯失败6.1 先查物理层接线、接地、屏蔽层串口通讯出问题我排查的第一顺位永远是物理层而不是程序。有一次现场设备偶发通讯失败查了两天程序最后发现是RS485的屏蔽层没接地变频器一启动就干扰。把屏蔽层单端接地后问题直接消失。接线方面几个要点RS485要A对A、B对B别接反通讯线用双绞屏蔽线屏蔽层单端接地敷设时和动力电缆保持距离。RS232则是RXD、TXD交叉接GND共地。很多新手以为RS232不共地也能通短距离勉强可以距离一长就乱码。6.2 缓冲区大小和扫描周期的博弈H3U的RS指令接收缓冲区大小是固定的你在指令里写了K50就最多收50字节。如果设备实际回帧超过50字节超出部分会被直接丢弃。所以配置前一定要确认设备最长帧不超过缓冲区。H5U这边容易踩的是另一个坑如果用周期性任务调用COM_Recv而任务周期比设备帧间隔还长就可能出现收两字节、再收两字节的碎片化现象。这时候要么把接收放到更快的任务里去要么把Timeout设置得比任务周期长让一帧完整数据在同一个任务周期内收完。还有一点接收缓冲区数据处理完务必清空或重置长度否则下一帧进来上一帧的残留数据可能被当作有效数据一起解析产生莫名其妙的重量值。6.3 串口助手是自由协议开发的第一生产力做自由协议通讯我的工作流里永远有一步先用电脑串口助手和现场设备单聊确认协议真实行为再写PLC程序。具体做法是电脑USB转RS485接设备串口助手按设备协议手动发请求帧观察设备回帧。这一步能确认三件大事设备的真实波特率和校验位、请求帧格式是否和文档一致、实际响应帧里每个字节的规律。我遇到过的仪表文档和实际行为不一样的情况一只手数不过来。确认没问题后把串口切到PLC。调试时串口助手还有一个妙用——并接在RS485总线上做监听PLC发出的每一帧、设备回的每一帧全部看得清清楚楚。哪一侧没发、哪一侧没回、校验是不是对一看便知。这套方法帮我解决过的偶发通讯失败比任何仿真都有效。6.4 最后补一个被坑过多次的细节自由协议模式下PLC串口的发送和接收方向切换是有延时的。RS485是半双工PLC发完一帧数据要等发送状态完全释放后才能切到接收。H3U发送完成后M8122自动复位但你如果紧接着就去查询接收设备回帧快的时候第一个字节可能在这个切换间隙里丢掉了。我的做法是发送完成后延时10~20ms再开启接收等待给方向切换留足时间。这个时间很短不影响整体节拍但能省掉大量丢第一个字节的烦恼。串口自由协议说到底就是配置串口、发字节、收字节、按约定解析这四板斧。你把它当成一个通用的字节搬运通道后面所有花活都建立在字节之上。把这一章里的RS指令套路、COM功能块调用、CRC实现和排查方法吃透回到现场不管接的是仪表、扫码枪还是老式变频器心里都有底。
返回列表