C#通过串口与三菱PLC通讯,读写M区内容

使用C#通过串口与三菱PLC通信并实现M区(辅助继电器区)读写,结合三菱MC协议和串口通信实现:


一、硬件与协议准备

  1. 硬件连接

    • 使用RS-485转USB模块连接PLC与PC
    • PLC需配置RS-485通信模块(如FX2N-485BD)
    • 接线规范:A+/B-对应485模块的RDA+/RDB-(需接120Ω终端电阻)
  2. 协议选择

    • 使用三菱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);

三、关键实现要点

  1. 协议解析规则

    • 起始符:0x02(STX)
    • 结束符:0x03(ETX)
    • 地址转换:M区地址需转换为十六进制(如M0→0x30)
    • 数据格式:7位ASCII编码(数字字符需转换为ASCII码)
  2. 异常处理

    try {
        plcPort.WriteTimeout = 3000;
        plcPort.Write(buffer, 0, buffer.Length);
    } catch (TimeoutException ex) {
        Debug.WriteLine($"通信超时: {ex.Message}");
    } catch (IOException ex) {
        Debug.WriteLine($"设备断开: {ex.Message}");
    }
    
  3. 性能优化

    • 使用异步通信:plcPort.BeginWrite()
    • 批量读写:单次操作不超过128字节
    • 数据缓存:使用MemoryStream暂存高频数据

四、调试与验证

  1. 监控工具
    • 使用三菱GX Works2的通信测试功能
    • 串口助手工具(如SecureCRT)抓包验证
  2. 常见问题
    • 校验失败:检查奇偶校验设置(7位数据+1位校验)
    • 无响应:确认站号设置和终端电阻(120Ω)
    • 数据错乱:验证ASCII编码转换逻辑

五、扩展应用

  1. 封装通信类

    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) {
            // 实现完整读操作
        }
    }
    
  2. 多线程处理

    Task.Run(() => {
        while (true) {
            byte[] data = plc.ReadM(0, 32);
            // 更新UI需Invoke
        }
    });
    

六、参考资料

  1. 三菱MC协议手册(官方文档)
  2. GX Works2通信参数配置指南
  3. HslCommunication开源库(支持高级功能)
  4. C#通过串口与三菱PLC通讯,读写M区内容 www.youwenfan.com/contentcne/111873.html
  5. 串口通信异常代码表通过上述方案,可实现稳定可靠的M区数据交互。实际开发中需根据具体PLC型号调整参数,并建议通过GX Works2进行通信参数预配置。
posted @ 2025-08-29 17:07  康帅服  阅读(107)  评论(0)    收藏  举报