三菱MC协议入门:3E帧二进制读写PLC实战

发布时间:2026/10/29 3:18:19
三菱MC协议入门:3E帧二进制读写PLC实战 简介《三菱MC协议配置和使用简析》是一份面向PLC初学者与自动化工程师的入门文档围绕外部设备通过MC协议读写三菱PLC内部寄存器展开重点解决TCP/IP通信配置、3E帧报文组织与错误排查等实际问题。资源包共1个docx文件大小约1.12MB内容以图文说明为主便于按章节查阅。已有4092人学习下载。文档从MC协议目的、485与TCP/IP通信方式切入梳理3E帧二进制通讯的发送与响应结构并给出PLC内置以太网端口设置、允许RUN中写入、端口号配置等操作要点同时以向D7000写入H000C、连续读取5个软元件为例解析报文字段附软元件类型与代码对应、指令及子指令列表、错误帧处理方法可帮助读者建立从参数配置到报文调试的完整思路。1. 先弄明白一件事MC 协议到底在解决什么问题很多刚接触工控的朋友第一次听到三菱 MC 协议脑子里冒出来的第一个问题是我又不做 PLC 编程学这个干嘛其实可以先做个类比。把 PLC 想象成一栋上了锁的仓库里面一格一格摆着数据D 区是货架M 区是一排开关标记X、Y 是进出货的记录。你在电脑上写程序也好用触摸屏也好想让仓库里某一格的数据变一下总得有人给你开一扇门。三菱 MC 协议就是这扇门的钥匙它是 PLC 自己带的一套通信规矩外部设备按固定格式敲门PLC 按固定格式回话于是你就能读走一个数、或者往某个寄存器里写进一个数。说白了学它不是为了改变 PLC 里正在跑的控制逻辑而是在原有程序之外多接一条数据通道。适合谁做上位机软件的、做设备数据采集的、做产线看板的以及像你我这样刚入门工控通信、想搞清楚「电脑和 PLC 到底怎么说话」的新手。下面不讲高深原理就带你从零把第一帧数据发出去。2. 为什么值得学不用停机改程序也能读写 PLC 数据2.1 先看看传统做法有多别扭想象一个很常见的需求产线上一台设备你想在办公室电脑上每分钟看一次某个数据寄存器里的累计产量顺便存到表格里做统计。如果不用 MC 协议走老路会是这样先在梯形图里加一段通信程序把要看的那个 D 值搬到固定的发送缓冲区再写触发条件和握手标志位然后上位机这边也要写一套对应的接收解析。整个过程有两个麻烦。第一是要动 PLC 程序改完得重新下载通常还得停机或者挑检修窗口第二是改动本身有风险加进去的通信逻辑可能占用扫描周期也可能和原来的联锁冲突万一改坏了产线停了责任就在你身上。我第一次做这种需求的时候因为一个握手位没处理好PLC 和上位机互相等对方数据卡住不动排查了大半天。这种血泪经验其实很典型问题不在通信本身而在于你动了一个本来不该动的程序。2.2 MC 协议的定位PLC 出厂就带的一扇窗MC 协议不一样的地方在于它是 PLC 自己内置的通信服务。你不需要写梯形图去实现它只需要在 PLC 的参数里做几项设置相当于告诉 PLC「在某个端口上开一扇窗允许外面的人按规矩来读写。」设置完把参数烧写进去这扇窗就一直开着你的电脑、上位机、扫码设备随时可以连上来。它的工作方式是「一发一收」。外部设备主动发起通信把一帧特定格式的网络数据发给 PLCPLC 收到后处理再返回一帧。如果收到的帧格式对返回的就是写入成功或者对应的数据如果帧格式错返回的帧里会带上错误类型告诉你是哪里不对。这里有个关键点新手一定要记住PLC 从不主动推送数据。它就像一个等着你提问的人你不问它不说话。所以你的程序结构必然是自己发请求、自己等回应而不是被动等它上报。传输层上MC 协议有 485 和 TCP/IP 两条路。这份资料只讲 TCP/IP 这一条另一条说实话思路是一样的帧内容也一样只是底下换了物理层。入门建议先把 TCP/IP 这条走通因为你在电脑上就能验证不需要额外的转换器。2.3 四种帧格式先认个脸3E、3C、4C、4EMC 协议的帧格式不止一种常见的有 3E、3C、4C、4E。新手看到这四个名字容易懵其实先不用全懂认个脸就行帧格式特点入门建议3E头部固定、长度字段清晰TCP 上最常用先学这个本文全部围绕它3C更早期的形式帧头和 3E 不一样遇到老设备再回头看4C在 3C 基础上做了扩展暂缓不影响入门4E报文字段更完整能表达更多信息暂缓等熟练了再补为什么先学 3E因为它的结构最规整先是一个固定的副头部接着是网络号、PLC 号、目标模块编号这些几乎不用改的字段然后是一个明确告诉你「后面还有多少字节」的长度字段最后才是指令和数据。结构规整意味着你可以一格格对着数不容易数错。其他三种的差别主要在头部字段的排布上等你把 3E 拆熟了再去看差别基本上是对着参考手册比一比就能明白。这份资料里也提到了《MELSEC 通讯协议参考手册》那是权威依据遇到拿不准的字段就去查它。2.4 二进制和 ASCII 怎么选新手直接选二进制除了帧格式通讯内容还分二进制和 ASCII 文本两种形式。这两种传的东西完全一样只是表现形式不同。打个比方你要告诉对方数字 12。用二进制就是两个字节0C 00一共 2 字节用 ASCII就是把 12 写成字符000C4 个字节。单看一个点差别不大但如果你一次读 100 个寄存器二进制是 200 字节ASCII 就是 400 字节一帧的长度直接翻倍。而且 ASCII 到了程序里还得做一次字符串转数字二进制拿到就能用。所以这份资料的结论很明确推荐二进制。帧更短、不用转换、效率更高。对新手来说还有个隐性好处二进制的长度是死板的、可预测的你算错一个字节马上就能发现ASCII 里混进一个空格你肉眼根本看不出来那才是真的玄学。提示二进制和 ASCII 不能混用。你在 PLC 参数里选了哪种数据代码帧里就得按哪种写混着来一定报错后面第 5 章会专门讲这个坑。2.5 先说清楚它不能干什么入门最怕的是把它当成万能的。有几条边界最好一开始就知道。第一它不能绕过 PLC 程序里的安全逻辑。MC 协议是给你读写软元件的通道但程序里该有的联锁、该有的保护它一概不管。你通过它强行写一个输出点PLC 该动作还是动作出了事没人替你挡。第二写入这件事是需要 PLC 那边授权的。参数里有个「允许 RUN 中写入」的勾选项不勾你在运行状态下写不进去只能读。这不是故障是设计如此。第三它只解决「怎么读写数据」不解决「数据是什么意思」。D7000 里那个数到底是温度还是产量MC 协议不知道得你自己和写程序的人对好点位表。3. 第一个例子跑通给 D7000 写一个数再读回来3.1 动手前的三样准备在敲代码之前先确认三件事都通了否则后面全是无效排查。第一PLC 的 IP 地址你知道而且和你的电脑在同一个网段。比如 PLC 是 192.168.1.10你的电脑就得是 192.168.1.x。第二PLC 参数里已经开好了 MC 协议的端口比如 4999。这一步在第 4 章详细讲先假设已经配好了。第三也是新手最常跳过的一步在你的电脑上 ping 一下 PLC 的 IP。ping 得通说明物理链路和网络层没问题后面出问题就只能是协议层ping 不通别急着怀疑协议先查网线、网段和防火墙。注意ping 不通的时候去调帧格式是纯浪费时间。先把网络打通再谈协议。3.2 3E 二进制帧的骨架一格格拆开看3E 帧的二进制形式一条请求帧由下面这些字段依次拼起来。注意这里说的「帧」不包含 IP 头和 TCP 头那些是操作系统协议栈自动加的你只管应用层这一段字段长度示例值说明副头部2 字节50 003E 帧二进制固定值网络号1 字节00默认值单机直连不用改PLC 号1 字节FF默认值请求目标模块 I/O 编号2 字节FF 03代表访问自身 CPU请求目标模块站号1 字节00默认值请求数据长度2 字节0E 00从监视定时器到数据末尾的字节数监视定时器2 字节10 00单位 250 毫秒16 即 4 秒指令2 字节01 14批量写入子指令2 字节00 00按字为单位起始软元件号3 字节58 1B 00D7000 的编号软元件代码1 字节A8二进制下 D 寄存器的代码点数2 字节01 00写 1 个写入数据2 字节 × 点数0C 00要写的值这张表里有两条规则是新手最容易栽的地方必须单独拎出来说。第一条两个字节的字段低位字节在前、高位字节在后。表里写的0E 00实际含义是十六进制的 0x000E也就是 14。表里写的10 00含义是 0x0010也就是 16。你心里想的数要倒着填进帧里。三个字节的软元件号也是同样的道理D7000 的十进制是 7000十六进制是 0x1B58写进帧里就变成58 1B 00。第二条请求数据长度要自己算。它不是整帧长度而是从监视定时器开始一直到最后一位数据的总字节数。算错了 PLC 会直接判定帧格式错误返回一个错误帧你连数据都看不到。3.3 把这一帧逐字节读一遍现在来看具体例子往 D7000 里写入 H000C也就是十进制的 12。完整的发送帧是这样一串十六进制50 00 00 FF FF 03 00 0E 00 10 00 01 14 00 00 58 1B 00 A8 01 00 0C 00我们对着上一节的表从左往右数50 00是副头部3E 帧二进制固定就这么写不用改。00是网络号FF是 PLC 号FF 03是目标模块编号00是站号。这五个字节是「地址信息」单机直连的场景下原样照抄就行入门阶段不用深究。0E 00是请求数据长度倒过来读是 0x000E14 字节。10 00是监视定时器倒过来读是 1616 × 250 毫秒 4 秒。意思是 PLC 最多等你 4 秒。01 14是指令倒过来读是 0x1401批量写入。00 00是子指令表示按字为单位处理不是一个位一个位处理。58 1B 00是起始软元件号倒过来拼是 0x1B58也就是十进制的 7000所以是 D7000。A8是软元件代码二进制下 D 寄存器用 A8 表示。01 00是点数倒过来是 1表示写 1 个。0C 00是写入的数据倒过来是 0x000C也就是十进制 12。再验算一下长度字段从10 00开始数到结尾是 2 2 2 3 1 2 2 14 字节和0E 00完全对得上。这一步核对很重要养成习惯之后你写的帧基本不会因为长度报错。PLC 处理成功后会返回这样一帧D0 00 00 FF FF 03 00 02 00 00 00副头部从50 00变成了D0 00这是响应帧的固定标志。后半段02 00是响应数据长度倒过来是 2最后的00 00是结束代码两个字节都是 0表示一切正常。只要结束代码不是 0就说明这条指令没执行成功得去查错误代码表。3.4 用一段 Python 把这一帧发出去知道了帧长什么样发出去其实只需要一个 TCP 连接。下面这段代码用 Python 标准库就能跑不需要装额外的通信库import socket # 这两个值必须和 PLC 参数里设置的一致否则连不上 PLC_IP 192.168.1.10 PLC_PORT 4999 # 3E 帧 / 二进制 / 批量写入向 D7000 写入 H000C frame_hex ( 5000 # 副头部3E 帧二进制固定值 00 # 网络号 FF # PLC 号 FF03 # 请求目标模块 I/O 编号 00 # 请求目标模块站号 0E00 # 请求数据长度14 字节 1000 # 监视定时器16 x 250ms 4 秒 0114 # 指令批量写入 0000 # 子指令按字为单位 581B00 # 起始软元件号D7000 A8 # 软元件代码D 寄存器 0100 # 点数1 个 0C00 # 写入值H000C ) frame bytes.fromhex(frame_hex) # 建立连接超时设 3 秒避免 PLC 不回话时程序一直卡着 with socket.create_connection((PLC_IP, PLC_PORT), timeout3) as s: s.sendall(frame) # 发出请求帧 resp s.recv(1024) # 接收响应帧 print(resp.hex( ).upper())这段代码的逻辑很直白把拼好的十六进制字符串转成字节连上 PLC 的 IP 和端口发出去再收一帧回来。几个地方可以按自己情况改PLC_IP和PLC_PORT换成你实际配置的值0C00换成你想写的数注意还是要低位在前如果要一次写多个寄存器就改点数并往后追加数据同时别忘了同步重算请求数据长度。超时设 3 秒是个经验值。设太长PLC 不回话时你的程序会僵在那里设太短网络稍有抖动就误判成失败。第一次跑通之后再按现场情况调。3.5 再读回 5 个软元件确认写完不算完得读回来看看是不是真的写进去了。读取 D7000 开始的连续 5 个软元件发送帧是这样50 00 00 FF FF 03 00 0C 00 10 00 01 04 00 00 58 1B 00 A8 05 00和写入帧比一比变化的地方只有三处请求数据长度从0E 00变成0C 00因为读取不带数据段少 2 字节指令从01 14变成01 04倒过来是 0x0401批量读取点数从01 00变成05 00读 5 个。地址部分一模一样还是 D7000。PLC 的响应是D0 00 00 FF FF 03 00 0C 00 00 00 0C 00 00 00 00 00 00 00 00 00拆开看D0 00是响应副头部后面是地址信息0C 00是响应数据长度倒过来是 12 字节00 00是结束代码正常再往后每 2 字节一个值依次是0C 00、00 00、00 00、00 00、00 00也就是 D7000 到 D7004 分别是 12、0、0、0、0。第一个 12 正是刚才写进去的说明整条链路通了。把这段解析写成代码就是下面这样import socket PLC_IP 192.168.1.10 PLC_PORT 4999 # 3E 帧 / 二进制 / 批量读取读 D7000 开始的 5 个寄存器 read_frame bytes.fromhex( 5000 00 FF FF03 00 0C00 # 请求数据长度12 字节 1000 # 监视定时器 0104 # 指令批量读取 0000 # 子指令按字为单位 581B00 # 起始软元件号D7000 A8 # 软元件代码D 寄存器 0500 # 点数5 个 ) with socket.create_connection((PLC_IP, PLC_PORT), timeout3) as s: s.sendall(read_frame) resp s.recv(1024) end_code resp[9:11] # 结束代码占第 9、10 两个字节 print(结束代码:, end_code.hex().upper()) if end_code b\x00\x00: # 0 表示指令执行成功 payload resp[11:] # 第 11 字节之后全是数据 values [ int.from_bytes(payload[i:i 2], little) # 小端还原成整数 for i in range(0, len(payload), 2) ] print(D7000 ~ D7004 , values) else: print(PLC 返回了错误去查错误代码表)这里的偏移量 9 和 11 不是随便写的响应帧前 9 个字节是副头部和各种地址信息接着 2 字节结束代码所以数据从第 11 字节开始。int.from_bytes(..., little)就是在做小端转换把0C 00还原成 12。两个细节建议养成习惯先判结束代码再解析数据因为出错时数据段的内容没有意义解析完成后把结果打印出来和 PLC 编程软件里的监控值对一眼对上了才算真通。4. PLC 侧怎么配五步设置一行梯形图都不用写4.1 前两步从工程栏进到内置以太网端口打开 PLC 编程软件在右侧的工程栏里找到「PLC 参数」双击打开。弹出来的对话框里有一堆项目找「内置以太网端口设置」点进去。第一次操作的人容易在这一步迷路因为参数项目太多名字又长得像。记住关键字内置、以太网。如果找不到很可能是你选的 PLC 型号本身不带网口那就走 4.5 讲的模块设置路线。进到这个页面之后你会看到 IP 地址、子网掩码、默认网关这些和普通网络设置一样的东西还有一个叫「通信数据代码设置」的选项。这一项决定了帧里数据是二进制还是 ASCII。按第 2 章的建议选二进制。这个选项和你的代码必须一致一旦定了就别改改了代码也得跟着改。4.2 第三、四步勾选「允许 RUN 中写入」并打开设置同一个页面里有个勾选项大意是「允许在 RUN 状态下写入」。这个必须勾上否则 PLC 在运行模式下只让你读、不让你写你会以为是帧写错了其实是权限没开。这是新手最常撞的一堵墙。接着点「打开设置」进到连接配置页面。第一栏里要做两个选择协议选 TCP通信方式选 MC 协议。然后填端口号这个号可以按自己需求定比如 4999只要不和你网络里其他服务冲突就行。填完点设置结束一层层退回去。端口号这个事多提一句PLC 侧填什么你代码里的PLC_PORT就得填什么两边对不上是连不上的而且是那种「TCP 连接直接被拒绝」的连不上症状很明显不难排查。4.3 第五步把配置烧写进去参数改完只是改在你电脑上的工程文件里PLC 那边还没生效。必须把新配置烧写到 PLC 中这一步不做前面全白干。烧写完成之后建议按这个顺序验证先看 PLC 上的网口指示灯亮不亮再从电脑 ping 一次 IP然后随便发一帧读指令看能不能收到响应。分三步走的好处是哪一步断了你能立刻定位不用在协议层瞎猜。4.4 没有自带网口怎么办走网络参数里的模块设置如果你的 PLC 本体没有内置网口而是插了一块以太网模块那设置的位置不一样要在网络参数里找到对应的模块再进去设置。好消息是设置过程和内置网口几乎一样也是 IP、通信数据代码、打开设置里选 TCP 和 MC 协议、填端口号、烧写。唯一的区别是你要先确认模块的槽位和编号别配到别的模块上去。4.5 配完还是连不上按这个顺序查配置这东西最怕的是改完没反应又不知道从哪查。给你一个从下往上的排查顺序照着走基本能定位物理层网口灯亮不亮网线有没有插好。网络层电脑能不能 ping 通 PLC 的 IP电脑和 PLC 是不是同网段。端口层PLC 参数里的端口号和代码里的端口号是否一致协议是否都选了 TCP。协议层发出去的帧副头部是不是50 00请求数据长度算得对不对。权限层写入失败但读取正常时回头检查「允许 RUN 中写入」有没有勾。这个顺序的逻辑是越底层的问题越先排除因为底层不通上面的现象全是假的。ping 不通的时候讨论帧格式纯属自己给自己找麻烦。5. 避坑清单新手最容易翻车的五个地方5.1 坑一数写进去了读出来是另一个数现象明明写了 12读回来变成 3072 或者别的怪数。原因字节序没处理。MC 协议里两字节字段是低位在前高位在后你按人习惯把高位写前面了。12 是 0x000C正确写法0C 00写成00 0C就变成了 3072。三个字节的软元件号同理。解决给所有多字节字段定一条死规矩——先在纸上把十六进制写出来再两位两位倒过来填。刚开始慢一点无所谓写顺手了自然就快了。5.2 坑二3E 和 3C 混着用怎么都连不上现象TCP 连接能建立但发出去没回应或者直接断开。原因帧格式和 PLC 侧配置对不上或者你抄了一段别人项目里的老帧那是 3C 格式的头部副头部和长度字段的位置都不一样。解决先确认 PLC 参数里选的是哪一种再确认代码里副头部写的是不是对应的值。入门就把 3E 二进制刻在脑子里别东抄一段西抄一段。5.3 坑三ASCII 的内容塞进二进制帧现象帧发出去PLC 回一个错误帧结束代码非 0。原因PLC 参数里选了二进制你代码里却按 ASCII 的方式填了000C这种字符形式。两种形式传的东西一样但字节排布完全不同PLC 一看长度对不上就直接判错。解决把「数据代码设置」和代码里的写法对齐要么全二进制要么全 ASCII。入门建议固定二进制因为字节数少、结构规整错了也好找。5.4 坑四软元件代码记错读到了隔壁区现象读取能成功结束代码也是 0但读回来的值明显不对而且怎么改地址都不对。原因软元件代码填错了。D 区在二进制下是 A8M 区、X 区、Y 区、W 区各有各的代码填错了 PLC 不会报错它只是老老实实把另一个区的数据给你。这种错误最阴因为它披着「成功」的外衣。解决把常用的软元件代码整理成一张小表贴在显示器边上或者写进代码注释里。资料里给了基本型 QCPU 下软元件名称和代码的对应关系分 ASCII 和二进制两套其他系列去查对应手册核对。地址和代码是配对使用的改地址的时候顺手看一眼代码别只改一半。5.5 坑五PLC 回了帧但你看不懂它在报错现象能收到响应但结束代码不是 0程序里解析出来的数据是乱值。原因你跳过了结束代码直接解析数据。出错的时候响应帧里根本没有有效数据段你按正常帧去切字节切出来的当然是垃圾。而且不同系列 PLC 的错误代码含义不完全一样。解决解析的第一件事永远是判断结束代码。非 0 就停下来把这两个字节记下来去查对应型号手册里的错误代码表。资料里举了某个系列的描述方式你可以照着那个格式去查自己的型号。养成「先判码、再解数据」的习惯能省掉大量瞎猜的时间。6. 下一步学什么从会发一帧到能稳定采集能手动拼出一帧、发出去、读回来其实已经跨过了最难的那道坎。接下来怎么走给你一条按顺序来的路径。先补软元件体系。把 D、M、X、Y、W、B、T、C 这些区搞清楚知道哪些是位单位、哪些是字单位、哪些是只读的。这一步不写代码就是对着点位表和手册看看懂了再动手。再把指令用全。入门只用了批量读0x0401和批量写0x1401实际还有按位读写、随机读写、多个块一起读这些指令配合不同的子指令能覆盖大部分场景。建议不要一次全学用到哪个查哪个查完记在笔记里。然后处理「一次读很多」的工程问题。真实采集不是读 5 个寄存器那么简单可能是几百个点、分布在不同的区、还要定时轮询。这里会碰到几个新问题要面对的问题入门做法后面要考虑的点位很多一帧读 5 个批量读、分块读、控制单帧长度需要定时采集手动跑一次轮询周期、超时重试、断线重连数据要落库打印到屏幕时间戳、异常值标记、断点续传多人同时访问单人调试连接数上限、请求排队最后是错误处理从「能看懂」到「能自愈」。入门阶段看到非 0 结束代码就去查表这没问题往后要进一步区分哪些错误重发一次就好哪些必须报警停机。我自己的教训是这样的早期做一个采集小工具图省事把「发一帧收一帧」写成了没有超时的阻塞调用结果现场网络抖了一下程序整整卡了十几分钟操作工以为电脑死机了。从那以后我每次写通信代码都强制走一遍「设超时、判结束代码、失败重试、重试还失败就断开重连」这四步哪怕只是写个临时脚本也不例外。多写的这十几行就是给自己留的后悔药。希望帮到你先把第一帧发出去剩下的路会越走越顺。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询