TRIO-Basic 从入门到精通(十三):Trio 与三菱 Q 实现 MC 协议通讯
本教程讲解Trio控制器作为主站、三菱Q系列PLC作为从站的MC协议以太网通讯,手工构造MC协议报文帧对D寄存器进行批量读写,支持精确超时、断线重连,为运动控制器与PLC协同控制提供完整范例。
"# TRIO-Basic 从入门到精通(十三):Trio 与三菱 Q 实现 MC 协议通讯\n\n## 一、教程背景\n\nMC 协议是三菱 PLC(如 Q 系列)基于以太网 TCP 的标配通讯协议,三菱 Q 系列自带以太网端口,默认协议即为 MC 协议。在自动化产线中,Trio 运动控制器常需与三菱 PLC 交换数据,掌握 MC 协议的帧格式与编程方法,是实现"运动控制器 + PLC"协同控制的关键一步。\n\n本教程以 Trio 为主站、三菱 Q 为从站,基于以太网 TCP 实现 MC 协议通讯,演示对 PLC 软元件(D 寄存器)的读写。该方法同样具有抛砖引玉的作用——掌握了帧构造原理,即可扩展对接更多支持 MC 协议的控制器或传感器。\n\n## 二、技术要点/技术方案\n\n测试配置:\n\n- 主站:Trio,IP 地址 192.168.0.251\n- 从站:三菱 Q,IP 地址 192.168.0.220,通讯端口 2000\n\n核心思路:\n\n- 使用 Trio 的串行/网络通道(本例 com_port=20)以 OPEN #com_port AS \"TCP:192.168.0.220(2000)\" FOR READ_WRITE 建立 TCP 连接。\n- 按 MC 协议帧格式手工构造请求报文(低字节在前):以"50 00 00 ff ff 03"开头的帧头标识三菱 Q 系列二进制帧,后续为监视/批量读、批量写命令、起始地址与长度等字段。\n- 读操作:读取 D100D119 共 20 个字(Len=0014),请求帧长度 0x000C。\n- 写操作:写入 2 个字到 D100 起始地址(Len=0002),数据由 D119 的请求字符串。\n5. 主循环中周期性调用 writedata1、writedata2 每次累加 5、10 后按高低字节拆分发送。\n- 用 GET/KEY 接收响应字节流,统计返回数据长度;以 read_timeout=250(ms)实现精确超时控制,超时后自动重开端口。\n\n程序特性:\n\n1. 通讯快速超时功能\n2. 断线重连功能\n3. 超时无响应重连功能\n4. 可设置准确的超时时间\n\n## 三、实施步骤\n\n1. 将 Trio 与三菱 Q 接入同一以太网,设置主站 IP 192.168.0.251、从站 IP 192.168.0.220(端口 2000)。\n2. 定义通道与变量:com_port=20、print_port=6、读取缓冲数组 read_array(256)、收发字符串缓冲及超时/轮询参数。\n3. 调用 open_port 子程序:先 CLOSE #com_port,再以 TCP:192.168.0.220(2000) 打开通道并清空缓冲。\n4. 调用 ready_readstr 子程序,按 MC 协议帧格式构造读取 D100start_read 与 start_write:发送请求帧、等待并接收响应,打印数据长度与耗时;超时则调用 open_port 重连。\n6. 依据响应帧首字节(如 $d0)判断是否收到正确应答,并可解析数据字放入 VR 变量供后续逻辑使用。\n\n## 四、代码示例\n\nbasic\nDIM com_port AS INTEGER\ncom_port=20\nTICKS=0\nDIM savelast_tick AS INTEGER\nsavelast_tick=0\nDIM print_port AS INTEGER\nprint_port=6\n\nDIM read_array AS INTEGER(256)\nDIM read_sendstr AS STRING(32)\nDIM write_sendstr AS STRING(64)\nDIM read_index,write_index AS INTEGER\nDIM get_str,clearbuf_len AS INTEGER\nDIM read_timeout,loop_time,save_looptick,writedata1,writedata2 AS INTEGER\nread_timeout=250\nloop_time=100\nsave_looptick=TICKS\n'=============================================================\nGOSUB open_port\nGOSUB ready_readstr\n\nWHILE TRUE\n GOSUB start_read\n GOSUB start_write\n\n REPEAT\n WA(5)\n UNTIL ABS(save_looptick-TICKS)>=loop_time\n save_looptick=TICKS\nWEND\n\n'=============================================================\nWA(50)\nSTOP\n'=============================================================\n'open port\nopen_port:\n\nCLOSE #com_port\nWA(20)\nOPEN #com_port AS \"TCP:192.168.0.220(2000)\" FOR READ_WRITE\nWA(20)\nGOSUB clear_buf\n\nRETURN\n\n'=============================================================\n'ready send read str\n'read data d100~d119\n'low->hight\n'50 00 send cmd\n'00 ff\n'ff 03\n'00 modid\n'0c 00 000c->12\n'10 00 0010->16*250ms\n'01 04 0401\n'00 00\n'64 00 00 adr=>00 00 64 ->100\n'a8 DADR\n'14 00 Len=0014 ->20\n'=============================================================\nready_readstr:\nread_sendstr=CHR($50)+CHR($00)\nread_sendstr=read_sendstr+CHR($00)+CHR($ff)\nread_sendstr=read_sendstr+CHR($ff)+CHR($03)\nread_sendstr=read_sendstr+CHR($00)\nread_sendstr=read_sendstr+CHR($0c)+CHR($00)\nread_sendstr=read_sendstr+CHR($01)+CHR($00)\nread_sendstr=read_sendstr+CHR($01)+CHR($04)\nread_sendstr=read_sendstr+CHR($00)+CHR($00)\nread_sendstr=read_sendstr+CHR($64)+CHR($00)+CHR($00)\nread_sendstr=read_sendstr+CHR($a8)\nread_sendstr=read_sendstr+CHR($14)+CHR($00)\n\nRETURN\n\n'=============================================================\n'ready write read str\n'write data d100~d119\n'low->hight\n'50 00 send cmd\n'00 ff\n'ff 03\n'00 modid\n'0c 00 000c->12\n'10 00 0010->16*250ms\n'01 04 0401\n'00 00\n'64 00 00 adr=>00 00 64 ->100\n'a8 DADR\n'14 00 Len=0014 ->20\n'=============================================================\nready_writestr:\nwrite_sendstr=CHR($50)+CHR($00)\nwrite_sendstr=write_sendstr+CHR($00)+CHR($ff)\nwrite_sendstr=write_sendstr+CHR($ff)+CHR($03)\nwrite_sendstr=write_sendstr+CHR($00)\n\n'write len\nwrite_sendstr=write_sendstr+CHR($10)+CHR($00)\n'time out\nwrite_sendstr=write_sendstr+CHR($01)+CHR($00)\n'write cmd\nwrite_sendstr=write_sendstr+CHR($01)+CHR($14)\n\nwrite_sendstr=write_sendstr+CHR($00)+CHR($00)\n'write adr\nwrite_sendstr=write_sendstr+CHR($64)+CHR($00)+CHR($00)\n\nwrite_sendstr=write_sendstr+CHR($a8)\n'len\nwrite_sendstr=write_sendstr+CHR($02)+CHR($00)\n\n'write data\nwritedata1=writedata1+5\nwritedata2=writedata2+10\nwrite_sendstr=write_sendstr+CHR(writedata1 AND $ff)+CHR((writedata1>>8) AND $ff)\nwrite_sendstr=write_sendstr+CHR(writedata2 AND $ff)+CHR((writedata2>>8) AND $ff)\n\nRETURN\n'=============================================================\nclear_buf:\nclearbuf_len=0\nWHILE KEY #com_port\n GET #com_port,get_str\n clearbuf_len=clearbuf_len+1\nWEND\nIF clearbuf_len>0 THEN PRINT #print_port,TIME$,\"Clear BufLen:\",clearbuf_len\n\nRETURN\n\n'=============================================================\nstart_read:\nGOSUB clear_buf\n\nPRINT #com_port,read_sendstr\nsavelast_tick=TICKS\nWA(20)\nread_index=0\nREPEAT\n WHILE KEY #com_port\n GET #com_port,get_str\n' PRINT #print_port,HEX(get_str)\n read_array(read_index)=get_str\n read_index=read_index+1\n WEND\nUNTIL ABS(savelast_tick-TICKS)>=read_timeout OR read_index>=51\nPRINT #print_port,TIME$,\"Read Data Len:\",read_index,ABS(savelast_tick-TICKS)\n'start read data\nIF read_array(0)=$d0 AND read_array(1)=$00 THEN\n' VR(0)=read_array(8)+ read_array(9)<<8\n' VR(1)=read_array(10)+ read_array(11)<<8\nENDIF\n\nIF ABS(savelast_tick-TICKS)>=read_timeout THEN\n PRINT #print_port,TIME$,\"Time Read Timeout=:\",ABS(savelast_tick-TICKS)\n GOSUB open_port\nENDIF\n\nRETURN\n\n'=============================================================\nstart_write:\nGOSUB clear_buf\nGOSUB ready_writestr\n\nPRINT #com_port,write_sendstr\nsavelast_tick=TICKS\nWA(20)\nread_index=0\nREPEAT\n WHILE KEY #com_port\n GET #com_port,get_str\n' PRINT #print_port,HEX(get_str)\n read_index=read_index+1\n WEND\nUNTIL ABS(savelast_tick-TICKS)>=read_timeout OR read_index>=11\nPRINT #print_port,TIME$,\"Write ret Data Len:\",read_index,ABS(savelast_tick-TICKS)\n'start read data\nIF ABS(savelast_tick-TICKS)>=read_timeout THEN\n PRINT #print_port,TIME$,\"Time Read Timeout=:\",ABS(savelast_tick-TICKS)\n GOSUB open_port\nENDIF\n\nRETURN\n\n\n## 五、应用价值\n\n1. 提供 Trio 与三菱 Q 系列 PLC 之间基于 MC 协议的以太网通讯完整范例,可直接套用。\n2. 通过手工构造报文帧,深入理解 MC 协议格式,便于扩展到三菱其他系列或其他厂商设备。\n3. 支持精确设定超时时间,配合快速超时与自动重连,保证产线通讯的稳定性。\n4. 读写分离的封装结构清晰,便于在运动控制程序中按需调用。\n5. 为"运动控制器+PLC"的典型产线架构提供了可靠的数据交互基础。\n\n## 六、SEO关键词\n\nTRIO运动控制器,TRIO-Basic,MC协议通讯,三菱Q系列,三菱PLC通讯,以太网TCP,Trio翠欧,运动控制\n\n---\n\n本文内容整理自 guimotion 的《TRIO-Basic从入门到精通教程》系列(CSDN,CC BY-SA 4.0),由 ZeroOne AI 重新组织编写。\n"
