三菱PLC MC协议通信与1E3E帧解析
1. 三菱PLC MC协议通信基础解析
三菱PLC的MC协议(Mitsubishi Communication Protocol)是工业自动化领域广泛使用的通信标准,它定义了上位机与PLC之间数据交换的规则和格式。在实际工业控制系统中,这种通信方式承担着关键的数据采集和设备控制功能。
MC协议支持多种物理层通信方式,包括RS-232、RS-485串口通信以及以太网通信。协议采用主从架构,上位机作为主站主动发起请求,PLC作为从站响应请求。通信过程遵循严格的报文格式,其中1E3E帧是MC协议中最常用的二进制帧格式,具有传输效率高、可靠性好的特点。
提示:1E3E帧名称来源于协议规范,其中"1E"代表请求帧的起始标识,"3E"代表响应帧的起始标识。这种命名方式在三菱PLC文档中通用。
在协议层次结构上,MC协议位于OSI模型的第7层(应用层),底层可以基于串行通信或TCP/IP协议。协议支持多种功能码,包括但不限于:
- 位设备读写(如X、Y、M等寄存器)
- 字设备读写(如D、W等寄存器)
- 批量读写操作
- 远程控制(RUN/STOP等)
2. 1E3E帧报文结构深度拆解
2.1 请求帧(1E帧)格式详解
标准的1E请求帧由以下几个部分组成,每个字段都有特定的含义和编码规则:
| 字段名称 | 长度(字节) | 说明 | |----------------|------------|----------------------------------------------------------------------| | 起始码 | 1 | 固定为0x1E,标识请求帧开始 | | 子头 | 2 | 高位字节表示网络编号(通常0x00),低位字节表示PLC编号(通常0xFF表示广播) | | 请求目标模块 | 2 | 固定为0xFF03,表示访问CPU模块 | | 请求数据长度 | 2 | 后续数据的字节长度(小端序) | | 监视定时器 | 2 | 通信超时时间(单位ms),常用0x0010表示16ms | | 命令代码 | 2 | 操作类型,如0x0401表示批量读,0x1401表示批量写 | | 子命令代码 | 2 | 细化操作类型,通常与主命令配合使用 | | 请求数据 | 可变 | 具体操作参数,如设备地址、点数等 | | 结束码 | 1 | 固定为0x0D,标识帧结束 |以读取D100开始的10个字为例,完整的请求帧可能如下:
1E 00 FF FF 03 0C 00 10 00 04 01 00 00 0A 00 44 00 64 00 0A 00 0D2.2 响应帧(3E帧)格式解析
3E响应帧的结构与请求帧对应,但包含PLC的处理结果:
| 字段名称 | 长度(字节) | 说明 | |----------------|------------|----------------------------------------------------------------------| | 起始码 | 1 | 固定为0x3E,标识响应帧开始 | | 子头 | 2 | 与请求帧相同 | | 响应源模块 | 2 | 固定为0xFF03,表示来自CPU模块 | | 响应数据长度 | 2 | 后续数据的字节长度(小端序) | | 结束代码 | 2 | 0x0000表示成功,其他值表示错误 | | 响应数据 | 可变 | 返回的数据内容 | | 结束码 | 1 | 固定为0x0D,标识帧结束 |成功读取D100-D109的响应帧示例:
3E 00 FF FF 03 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0D2.3 CRC校验计算与验证
MC协议使用CRC-16校验确保数据完整性,多项式为0xA001。以下是C#实现代码:
public static ushort CalculateCrc(byte[] data) { ushort crc = 0xFFFF; for (int i = 0; i < data.Length; i++) { crc ^= data[i]; for (int j = 0; j < 8; j++) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= 0xA001; } else { crc >>= 1; } } } return crc; }注意:CRC计算时应排除帧头和帧尾(即不包含起始码1E/3E和结束码0D),只对中间数据进行校验。
3. C#上位机开发实战
3.1 通信基础环境搭建
开发三菱PLC通信上位机需要准备以下环境:
- Visual Studio 2019或更高版本
- .NET Framework 4.7.2+或.NET Core 3.1+
- 三菱PLC编程软件(GX Works2/3)用于PLC参数配置
- 物理连接:根据PLC型号准备RS-232电缆或以太网线
对于FX5U等新型PLC,需要在GX Works3中启用内置以太网端口并设置MC协议参数:
- 设置IP地址和子网掩码
- 开放端口号(默认5001/TCP)
- 设置通信协议为MC协议
- 配置站号和网络参数
3.2 核心通信类设计
以下是完整的C#通信类实现,包含基本的读写功能:
public class MitsubishiMcProtocol { private TcpClient _tcpClient; private NetworkStream _stream; private readonly string _ipAddress; private readonly int _port; private readonly int _timeout; public MitsubishiMcProtocol(string ip, int port = 5001, int timeout = 1000) { _ipAddress = ip; _port = port; _timeout = timeout; } public bool Connect() { try { _tcpClient = new TcpClient(); var result = _tcpClient.BeginConnect(_ipAddress, _port, null, null); bool success = result.AsyncWaitHandle.WaitOne(TimeSpan.FromMilliseconds(_timeout)); if (!success || !_tcpClient.Connected) { _tcpClient.Close(); return false; } _stream = _tcpClient.GetStream(); _stream.ReadTimeout = _timeout; _stream.WriteTimeout = _timeout; return true; } catch { return false; } } public void Disconnect() { _stream?.Close(); _tcpClient?.Close(); } public byte[] ReadDevice(string device, int points) { // 构建读请求帧 var request = BuildReadRequest(device, points); // 发送请求 _stream.Write(request, 0, request.Length); // 接收响应 var response = new byte[1024]; int bytesRead = _stream.Read(response, 0, response.Length); // 解析响应 return ParseReadResponse(response, bytesRead); } private byte[] BuildReadRequest(string device, int points) { // 实现具体的请求帧构建逻辑 // 包括设备类型解析、地址转换等 } private byte[] ParseReadResponse(byte[] data, int length) { // 实现响应帧解析逻辑 // 包括错误检查、数据提取等 } }3.3 设备地址映射与转换
三菱PLC使用特定的地址编码规则,上位机需要正确转换:
| PLC设备类型 | 前缀 | 示例地址 | 说明 |
|---|---|---|---|
| 输入继电器 | X | X0 | 位设备 |
| 输出继电器 | Y | Y10 | 位设备 |
| 内部继电器 | M | M100 | 位设备 |
| 数据寄存器 | D | D100 | 字设备 |
| 文件寄存器 | R | R0 | 字设备 |
地址转换示例代码:
private (byte deviceCode, ushort address) ParseDeviceAddress(string device) { char prefix = device[0]; int num = int.Parse(device.Substring(1)); return prefix switch { 'X' => (0x9C, (ushort)num), 'Y' => (0x9D, (ushort)num), 'M' => (0x90, (ushort)num), 'D' => (0xA8, (ushort)num), 'R' => (0xAF, (ushort)num), _ => throw new ArgumentException("Unsupported device type") }; }4. 完整工程实现与调试技巧
4.1 工程架构设计
建议采用分层架构设计:
MCProtocolDemo/ ├── MitsubishiPlc/ # PLC通信核心库 │ ├── McProtocol.cs # 协议实现 │ └── DeviceMapper.cs # 地址映射 ├── Models/ # 数据模型 │ └── PlcDataModel.cs ├── Services/ # 业务服务 │ └── DataService.cs └── Views/ # 用户界面 ├── MainForm.cs # 主界面 └── MonitorControl.cs # 自定义控件4.2 典型通信流程实现
完整的读写操作流程示例:
// 初始化通信 var plc = new MitsubishiMcProtocol("192.168.1.10"); if (!plc.Connect()) { MessageBox.Show("PLC连接失败"); return; } try { // 读取D100开始的10个字 var data = plc.ReadDevice("D100", 10); // 处理数据... short[] values = new short[10]; for (int i = 0; i < 10; i++) { values[i] = BitConverter.ToInt16(data, i * 2); } // 写入数据示例 short newValue = 1234; byte[] writeData = BitConverter.GetBytes(newValue); plc.WriteDevice("D200", writeData); } finally { plc.Disconnect(); }4.3 调试技巧与常见问题
通信连接失败排查:
- 确认PLC IP地址和端口号
- 检查防火墙设置(关闭或添加例外)
- 使用ping测试网络连通性
- 用Wireshark抓包分析TCP连接
数据读写异常处理:
- 检查设备地址是否正确(注意起始地址和点数)
- 验证设备是否可读写(某些区域可能受保护)
- 确认PLC处于RUN模式(某些操作需要RUN状态)
性能优化建议:
- 批量读写减少通信次数
- 合理设置超时时间(通常500-1000ms)
- 对频繁访问的数据建立缓存机制
- 使用异步通信避免UI卡顿
特殊寄存器访问:
- 系统寄存器(如SD、SM)需要特殊权限
- 文件寄存器访问需要先指定文件号
- 扩展模块地址需要加上模块偏移量
我在实际项目中发现,三菱FX5U系列PLC对连续读取的点数有限制(通常最大960点),超过这个限制需要分多次读取。此外,某些旧型号PLC对TCP连接数有限制,长时间不通信可能导致连接断开,需要实现心跳机制保持连接。
