C#通过串口与三菱PLC通讯,读写M区内容
使用C#通过串口与三菱PLC通信并实现M区(辅助继电器区)读写,结合三菱MC协议和串口通信实现:
一、硬件与协议准备
-
硬件连接
- 使用RS-485转USB模块连接PLC与PC
- PLC需配置RS-485通信模块(如FX2N-485BD)
- 接线规范:A+/B-对应485模块的RDA+/RDB-(需接120Ω终端电阻)
-
协议选择
-
使用三菱MC协议(MELSEC Communication Protocol)
-
默认串口参数:
波特率: 9600 数据位: 7 停止位: 2 校验位: 偶校验
-
二、C#串口通信实现
1. 串口初始化
using System.IO.Ports;
SerialPort plcPort = new SerialPort();
plcPort.PortName = "COM3"; // 根据实际端口修改
plcPort.BaudRate = 9600;
plcPort.DataBits = 7;
plcPort.Parity = Parity.Even;
plcPort.StopBits = StopBits.Two;
plcPort.Handshake = Handshake.None;
plcPort.ReadTimeout = 5000;
plcPort.WriteTimeout = 5000;
plcPort.Open();
2. 数据帧构造(MC协议)
读M区指令格式(以读取M0-M1F为例):
byte[] ReadMArea(int startAddr, int length) {
byte[] command = new byte[] {
0x02, 0x37, 0x30, 0x37, 0x30, 0x35, 0x03, // 起始符+设备类型
0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 站号0
0x30, 0x31, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, // 起始地址M0
0x30, 0x32, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36 // 读取长度32字节
};
byte checksum = CalculateChecksum(command);
command[command.Length - 2] = checksum;
return command;
}
byte CalculateChecksum(byte[] data) {
byte sum = 0;
foreach (byte b in data) sum += b;
return (byte)(-sum & 0xFF);
}
3. 数据读写操作
// 读取M区
byte[] readCmd = ReadMArea(0, 32);
plcPort.Write(readCmd, 0, readCmd.Length);
byte[] response = new byte[plcPort.BytesToRead];
plcPort.Read(response, 0, response.Length);
// 解析响应数据(位操作)
BitArray bitArray = new BitArray(response.Skip(6).Take(32).ToArray());
bool m0 = bitArray[0]; // M0状态
bool m15 = bitArray[15]; // M15状态
// 写入M区(示例:设置M0为ON)
byte[] writeCmd = new byte[] {
0x02, 0x37, 0x30, 0x37, 0x30, 0x35, 0x03, // 起始符
0x36, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, // 站号0
0x30, 0x31, 0x30, 0x31, 0x30, 0x32, 0x30, 0x33, // 起始地址M0
0x30, 0x32, 0x30, 0x34, 0x30, 0x35, 0x30, 0x36, // 写入长度1字节
0x30, 0x31, 0x30, 0x33, 0x30, 0x34, 0x30, 0x35 // 数据01(二进制00000001)
};
byte writeChecksum = CalculateChecksum(writeCmd);
writeCmd[writeCmd.Length - 2] = writeChecksum;
plcPort.Write(writeCmd, 0, writeCmd.Length);
三、关键实现要点
-
协议解析规则
- 起始符:
0x02(STX) - 结束符:
0x03(ETX) - 地址转换:M区地址需转换为十六进制(如M0→0x30)
- 数据格式:7位ASCII编码(数字字符需转换为ASCII码)
- 起始符:
-
异常处理
try { plcPort.WriteTimeout = 3000; plcPort.Write(buffer, 0, buffer.Length); } catch (TimeoutException ex) { Debug.WriteLine($"通信超时: {ex.Message}"); } catch (IOException ex) { Debug.WriteLine($"设备断开: {ex.Message}"); } -
性能优化
- 使用异步通信:
plcPort.BeginWrite() - 批量读写:单次操作不超过128字节
- 数据缓存:使用
MemoryStream暂存高频数据
- 使用异步通信:
四、调试与验证
- 监控工具
- 使用三菱GX Works2的通信测试功能
- 串口助手工具(如SecureCRT)抓包验证
- 常见问题
- 校验失败:检查奇偶校验设置(7位数据+1位校验)
- 无响应:确认站号设置和终端电阻(120Ω)
- 数据错乱:验证ASCII编码转换逻辑
五、扩展应用
-
封装通信类
public class MelsecPLC { private SerialPort _port; public bool Connect(string portName) { _port = new SerialPort(portName, 9600, Parity.Even, 7, StopBits.Two); _port.Open(); return _port.IsOpen; } public byte[] ReadM(int startAddr, int length) { // 实现完整读操作 } } -
多线程处理
Task.Run(() => { while (true) { byte[] data = plc.ReadM(0, 32); // 更新UI需Invoke } });
六、参考资料
- 三菱MC协议手册(官方文档)
- GX Works2通信参数配置指南
- HslCommunication开源库(支持高级功能)
- C#通过串口与三菱PLC通讯,读写M区内容 www.youwenfan.com/contentcne/111873.html
- 串口通信异常代码表通过上述方案,可实现稳定可靠的M区数据交互。实际开发中需根据具体PLC型号调整参数,并建议通过GX Works2进行通信参数预配置。

浙公网安备 33010602011771号