ARTICLE DETAIL

资讯详情

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

基恩士扫码枪与三菱PLC的MC协议通信全解析

基恩士扫码枪与三菱PLC的MC协议通信全解析 简介面向C#开发与工业自动化工程师资源包提供基于MC协议访问基恩士、三菱PLC寄存器的完整实现方案。内容覆盖D、W、X、Y寄存器及INT16、INT32、FLOAT、DOUBLE等数据类型读写适合需要实现上位机与PLC数据交互、远程监控的开发者。压缩包共70个文件约176KB以C#源码21个cs、项目配置csproj、json、props及说明文档md、txt为主并包含可运行的解决方案与示例工程便于直接研究或二次开发。目前已有1314人学习下载。通过阅读源码可掌握连接建立、寄存器寻址、数据解析与连接释放等关键环节为快速集成三菱或基恩士PLC通信能力提供实用参考。 这两年做产线追溯项目几乎每次都会被同一个问题卡住基恩士的扫码枪已经到了三菱PLC的程序也改好了但两边怎么把数据接通一直没人给一个准话。做视觉也好、扫码也好基恩士是出镜率最高的那批设备而三菱PLC在中小型产线里又是绝对的主力。标题里写的“支持基恩士、三菱PLC MC协议”说白了就是在这样一个背景下被逼出来的——做一个上位机中间件一头接基恩士扫码枪的TCP/IP数据另一头通过MC协议把条码写进三菱PLC顺带把触发、完成、异常这些信号也一并打通。这套方案适合谁适合正在做产线追溯、防错防呆、设备联网的项目尤其是第一次碰基恩士扫码枪或者第一次碰三菱MC协议的工程师。下面把协议报文、设备对接、调试踩坑都按实际做过的路子整理出来照着走能少折腾好几天。1. 先搞清楚基恩士和三菱PLC在产线上各自扮演什么角色1.1 一套标准的扫码追溯架构其实有三层产线上的“扫码枪读到条码PLC决定放行还是拦截”听起来简单实际上中间必须有个翻译。基恩士SR1000这类读码器即使是支持TCP/IP的型号它吐出来的也只是一串ASCII字符。PLC那边要的不是字符串而是写入D寄存器或M继电器的具体数据这中间必须有人完成一次从“字符流”到“MC协议报文”的转换。我的做法是做一个常驻上位机网关三层的分工是这样的基恩士扫码枪负责采集条码按设定好的通讯方式把结果发出来上位机软件作为中间桥梁接收条码后按规则解析再调用MC协议指令写入三菱PLCPLC侧则通过程序判定数据合法性并给出OK或NG信号。这个架构的好处是调试的时候每一层都可以单独验证先用TCP工具测扫码枪的数据输出再用MC协议调试器测PLC读写最后把两边串起来。1.2 MC协议为什么是“必须会”的通信方式MC协议Mitsubishi Communication Protocol是三菱PLC以太网通信最常用的协议往上走有MC协议、SLMP、内置以太网功能本质上核心都是一套东西。不管你是用Q系列内置以太网口、QJ71E71以太网模块还是L系列只要走以太网和上位机通信绝大部分情况都会落到MC协议上。顺带说一句昆仑通泰触摸屏连三菱Q系列底层用的也是MC协议只是触摸屏组态软件帮你把报文封装好了。所以很多人会遇到“触摸屏能连上自己写程序却连不上”的怪现象——原因往往是触摸屏占用了通信通道或者PLC侧的连接数已经满了。这个问题后面单独说。1.3 基恩士扫码枪的通讯方式怎么选基恩士SR1000系列支持RS-232C、RS-422、以太网等多种输出方式。在以太网模式下可以把它配置成TCP客户端主动连上位机也可以配置成TCP服务端等上位机来连。实际项目里我更喜欢让扫码枪作为TCP服务端上位机去做客户端连接这样扫码枪重启后它自己会监听端口上位机只负责掉线重连逻辑上更稳定。也有厂家直接把基恩士扫码枪接到PLC的串口或以太网上通过MC协议让PLC直接读扫码枪数据。但这种做法对PLC编程要求高而且调试权限全在设备侧出了问题很难定位。我的建议是如果现场已经有上位机工控机、触摸屏一体机就让上位机来做中转灵活性和可维护性都更好。2. 三菱侧的核心把MC协议报文彻底拆开2.1 3E帧的结构与字节序容不得半点错MC协议在以太网传输时主要用3E帧它和串口上的1E帧/4E帧有明显区别。3E帧里藏着一个固定头然后是网络号、PC号、IO编号这些“路由信息”后面才是真正的请求数据。最容易摔跟头的地方是字节序MC协议里字数据都是低字节在前也就是小端存储。比如D100这个地址十进制100转成十六进制是0x0064在报文里要写成64 00而不是00 64。一个典型的批量读取D寄存器请求帧是这样的十六进制50 00 00 FF FF 03 00 0B 00 10 00 01 04 00 A8 64 00 00 02 00其中50 00子帧头固定值标识这是3E帧以太网访问00网络号通常填0FFPC号通常填0xFFFF 03请求目标模块IO编号默认0x03FF低字节在前00请求目标模块站号0B 00请求数据长度这里是从“监视定时器”到“点数”的11个字节10 00CPU监视定时器单位是250ms0x0010表示4秒超时01 04指令代表“批量读取字单位”00 A8设备类型0x00A8表示D数据寄存器64 00 00起始地址即D10002 00要读取的点数这里读2个字如果PLC正常返回响应帧会是50 00 00 FF FF 03 00 09 00 00 00 64 00 C8 00第9、10字节是结束代码00 00表示正常。后面每2个字节就是一个字的数据。2.2 读和写两个指令包覆盖90%的需求批量写入的指令是01 14也是按字写入。比如要把D100和D101分别写成200和0请求帧是50 00 00 FF FF 03 00 0F 00 10 00 01 14 00 A8 64 00 00 02 00 C8 00 00 00对比读取就能发现只是指令从01 04换成了01 14数据段尾部追加了要写入的值数据长度也相应多了4个字节。对你要提前自己算好这个长度PLC不会帮你纠正长度写错帧直接就被丢弃了。批量读取位设备时指令换成01 01设备码也跟着换X输入是9C 00Y输出是94 00M中间继电器是90 00。位设备的响应并不是一个BIT对应一个字节而是把若干个BIT按位打包返回这和你做MODBUS读取线圈数据时的处理方式是一样的。所以我在项目里原则是需要反馈到PLC时优先用D寄存器传数据、M寄存器传状态。因为M寄存器写起来能直接驱动PLC内部逻辑在触摸屏上也能直接看到状态调试期非常友好。2.3 设备码表与地址换算写错一个就全盘皆输这里放一张我常用的设备码对照表省得每次翻手册设备设备类型码字单位设备类型码位单位说明X输入--0x009C十六进制地址如X0对应0x00Y输出--0x0094十六进制地址如Y10对应0x10M继电器--0x0090十进制地址如M0对应0x00L锁存继电器--0x0092十进制地址D数据寄存器0x00A8--十进制地址W链接寄存器0x00B4--十六进制地址R文件寄存器0x00AF--十进制地址B链接继电器--0x00A0十六进制地址地址换算最大的坑是X、Y、W这类设备地址序号在PLC里显示为十六进制比如Y10它实际的十六进制地址就是0x0010。而D、M、R这些设备序号是十进制直接用就行。你要是把Y10当成十进制10去算报文里的地址就会变成0x000A那操作就跑到Y10前面的某个点上去了。基恩士和三菱在协议栈里的处理策略很不同。基恩士的TCP/IP通讯更偏向“把数据发出去就算完”你有疑问还得自己从返回值里抠。三菱MC协议则是一问一答必须有响应而且在数据链路层相对严谨。这两个风格放在一个项目里需要你在上层做一点点适配不至于冲突。3. 基恩士扫码枪接入数据从条码到变量的全过程3.1 SR1000的网络参数设置和触发模式基恩士SR1000的通信参数通常不是在本机菜单里设的而是用基恩士的专用设置软件如SR1000的AutoID网络通讯配置工具通过以太网连上后改配置。需要关注的几个点IP地址、子网掩码、网关必须和上位机在同一个网段协议类型选TCP/IP传输模式选“TCP服务端”还是“TCP客户端”以及监听端口号数据输出格式是触发后输出一次还是持续输出是ASCII原始数据还是带前缀/结束码的格式如果现场没有专用软件也可以先用底层网络扫描工具确认读码器的IP然后用TCP/UDP调试工具去连它的端口。实测下来SR1000监听的默认端口一般是9000口也可以自定义这在上位机配置里要能灵活填。触发模式这块我一般不开“连续读取”而是用传感器触发或外部信号触发。否则扫码枪会高频吐数据上位机队列很容易被同一张条码反复塞满。如果你在产线调试时发现PLC里的条码一直在变先别查PLC大概率是扫码枪一直在重复扫描。3.2 上位机接收扫码结果的程序骨架扫码枪把条码按ASCII字符串发出来通常以回车换行结尾。上位机这边只需要一个简单的TCP监听流程。C#里最直接的写法是这样的TcpListener listener new TcpListener(IPAddress.Any, 9000); listener.Start(); while (true) { // 等待扫码枪连接 using TcpClient client await listener.AcceptTcpClientAsync(); using NetworkStream stream client.GetStream(); byte[] buffer new byte[1024]; int read await stream.ReadAsync(buffer); string recv Encoding.ASCII.GetString(buffer, 0, read); string barcode recv.TrimEnd(\r, \n); Console.WriteLine($Scan: {barcode}); }这只是骨架实际上必须处理沾包和半包。TCP是流式协议扫码枪一次发送的ASCII也可能因为网络断开被分成两次到达或者一次把上次的残留一起带过来。处理办法是维护一个接收缓冲区按结束符CR/LF切包而不是每次都把收到的数据当成完整一帧。3.3 条码数据的清洗和防重策略基恩士扫码枪的输出格式可能带一些“附加物”比如在数据前面加[S]、后面加[E]或者加一个表示读取成功与否的头部标记。在项目早期我建议把收到的原始数据先打印出来确认格式后再做截取不要在没看清原始数据的情况下直接做字符串处理。条码里的空格也要特别注意。很多二维码本身不含空格但扫码枪的默认配置可能会在数据内插入分组符号。遇到这种情况先确认码制确认条码内容本身是什么再决定是保留还是剔除。防重逻辑建议做三层上位机记录最后一次读取内容如果和上次相同并且两次间隔小于设定阈值就直接丢弃写入PLC后要等PLC返回“已处理”信号在此之前不再接收新的扫码结果队列中只保留最新一条条码避免积压。4. 网关核心怎么把扫码数据安全写进三菱PLC4.1 整体架构一个监听线程一个写PLC线程我在工程里一般起两个线程一个专门接收扫码数据把合法的条码放进阻塞队列另一个专门消费队列逐条调用MC协议客户端写入PLC。这比“收到一条就立刻写PLC”的模式稳定得多因为当PLC侧超时或上位机卡顿时扫码枪不会阻塞产线不会因为上位机在处理旧数据而漏掉新扫码。代码层面可以用Channel或者BlockingCollection来当队列。每次扫码结果是典型的“生产”事件写PLC失败重试是“消费”过程两者解耦后排查问题也容易——看队列长度就知道是接收端卡了还是PLC写入卡了。4.2 字符串条码转成D寄存器数据要注意ASCII长度三菱PLC的D寄存器一个占16位也就是2个字节。一个条码字符串如果要存到D寄存器先要把字符转成ASCII码然后每两个字节拼成一个字。比如条码是“AB12”对应的ASCII十六进制是41 42 31 32那么D100里存0x4241D101里存0x3231。写入代码的核心部分如下public void WriteBarcodeToD(int startAddress, string barcode) { byte[] ascii Encoding.ASCII.GetBytes(barcode); int wordCount (ascii.Length 1) / 2; ushort[] values new ushort[wordCount]; for (int i 0; i ascii.Length; i 2) { ushort v ascii[i]; if (i 1 ascii.Length) v | (ushort)(ascii[i 1] 8); values[i / 2] v; } plc.WriteWords(0xA8, startAddress, values); plc.WriteBit(0x90, 100, true); // 置位M100通知PLC有新的条码 }这样写有个隐含约定PLC侧解析时要按同样的“低字节在前”逻辑把D寄存器还原成字符串。所以上位机和PLC程序最好由同一个工程师统一规划或者两头文档写得清清楚楚。最怕的是上位机按小端写入PLC侧按大端解析出来的字符串就会是乱的。还有一点条码里如果包含中文就需要用UTF-8或Shift-JIS编码而不是ASCll否则会丢字符。扫码枪的条码一般以ASCII为主但万一项目里扫的是带中文的QR码这块要提前测。4.3 写入完成后的确认和重试MC协议是“发指令-等响应”的模式所以写入是否成功直接看响应帧的结束代码就行。正常情况下结束代码是00 00不为0就是PLC侧拒绝了请求。我在网关里对写入失败的策略是重试3次每次间隔500ms如果3次都不行就置位一个“通信故障”寄存器并在上位机界面弹窗。千万不要无限制重试否则PLC侧刚恢复时队列里全是要写的旧条码反而把新数据顶掉了。读取D寄存器时也建议加超时。TCP连接上的Read操作如果不设置超时PLC死机时你的线程会永远挂在那里。设个3000毫秒的超时超时就断线重连这种处理在产线上能扛很多意外。4.4 把“支持基恩士、三菱PLC MC协议”做成可扩展结构代码写多了你会发现所谓的“支持多品牌”本质上就是抽象接口。我把接收设备和写入设备各定义成接口接收设备接口Connect()、Disconnect()、OnDataReceivedPLC写入接口Connect()、ReadWords()、WriteWords()、ReadBit()、WriteBit()这样基恩士扫码枪是三菱MC协议之外的一类实现将来换成康耐视、海康读码器只是换一个接收端实现类将来PLC换成汇川、信捷甚至西门子也只是换一个PLC实现类。这个项目叫“支持基恩士、三菱PLC MC协议”但骨架上你不能只留死代码否则下一个项目又得推倒重来。5. 现场调试踩过的坑每一条都是花钱买来的5.1 基恩士扫码枪连不上的排查链路先看网络层再谈协议层这是我一贯的排查顺序。扫码枪连不上的时候我先ping一下扫码枪IP能ping通再查端口如果ping不通百分之八九十是IP没配对或者扫码枪的网口没激活。如果用TCP调试工具连不上端口检查扫码枪是不是被配置成了UDP模式或者服务端程序没起来。另一个容易忽略的点Windows防火墙。有些工控机上装的杀毒软件会把监听端口给过滤掉导致扫码枪主动连接被拒。这种情况在开发机上极少出现因为开发机一般不跑那些安全软件一部署到现场就出问题。排查时直接看Windows安全中心的“防火墙和网络保护”把程序所在目录或监听端口加白名单。5.2 MC协议读写超时根因往往不在报文上MC协议报文格式错了拿到的通常是结束代码0xC051、0xC055这类错误而不是超时。如果你遇到的是超时也就是一直没响应那问题多半在网络通道上而不是报文本身。具体来说我先用Network AnalyzerWireshark抓包看请求帧到底有没有发出去以及PLC的回复帧有没有回来。能看到回复但程序超时就是响应解析的字节位置读错了完全看不到回复那就是连接断了或者PLC侧没把以太网通信参数配好。MC协议的TCP连接其实是长连接。如果上位机代码里每次读写都new一个TcpClient不仅慢还容易触发PLC的连接数限制因为每断开一次PLC侧保留的socket资源要过一段时间才释放。正确做法是初始化一次连接后面所有指令复用同一个NetworkStream再加一个断线重连机制。5.3 触摸屏和上位机同时连PLC的坑三菱Q系列的内置以太网口或者以太网模块同时允许的MC协议连接数是有限制的常见是8个或者16个。一个昆仑通泰触摸屏占一个连接上位机占一个连接你还开着GX Works2在线监控、GX Simulator模拟器、MC协议调试工具这些加起来很容易把连接数占满。解决办法是在线调试的时候把不用的连接全部断开。尤其是GX Works2的在线监视它不只是占一个通道有时还会影响PLC的响应优先级。把这些都关掉后再测试上位机通信通常就正常了。另外一个网络规划问题如果触摸屏、PLC、上位机在同一个网段IP分配要避免冲突。我在一个项目里就遇到过触摸屏的IP和上位机的虚拟网卡IP撞车导致PLC的数据时通时断。最简单的办法是给PLC固定一个专门IP段比如192.168.3.x触摸屏和上位机各占一个固定IP统一写到图纸备注里。5.4 PLC程序里没有对应的处理逻辑功能还是不通这是最容易忽略的一层。上位机把条码写进D100了M100也置位了但PLC程序里如果没有“当M100为ON时把D100的字符串解析并执行判断”的逻辑外面看起来依然是不通的。我一般给PLC程序留的接口非常明确D100开始存条码ASCII值M100上升沿表示“新条码到达”M101由PLC程序置位表示“数据已处理”上位机写完后等待M101收到后清掉M100并复位M101。这样两边各管各的不会互相把对方的状态覆盖掉。最后再分享一个小技巧我在做MC协议调试时除了正常的业务程序还会留一个“协议自检”功能上位机上做个按钮手动发一条固定的批量读取指令比如读取D0和D1然后把响应帧的十六进制打印在日志里。这个功能看起来不起眼但它能帮你把“网络问题”和“业务数据问题”瞬间分开。以后现场再报通信故障先点一下自检能读到说明网络和协议都是好的那就是上层逻辑的问题不能读到再抓包查通道。基恩士扫码枪那侧也可以做一个等价的自检上位机界面显示当前收到的最后一条原始字符串原文而不是解析后的条码。这样一旦出现条码不对你能立刻判断是扫码枪吐出来的就不对还是协议转换过程改坏了。产线调试这件事尽早把问题隔离在某一段比什么花哨的功能都管用。本文还有配套的精品资源点击获取
返回列表