C#与台达PLC通信

C#与台达PLC通信,整合了Modbus协议实现和工业级调试技巧,包含串口/以太网双模式支持


一、硬件配置要点

1. PLC参数设置(以DVP-ES3为例)

1. 通信接口配置:
   - 串口模式:RS-485(需外接转换器)
   - 波特率:9600(默认)
   - 数据位:8
   - 停止位:1
   - 校验位:None

2. Modbus从站设置:
   - 站号:1-247(需与上位机一致)
   - 功能码支持:03(读保持寄存器)/06(写单个寄存器)/16(写多个寄存器)

2. 网络拓扑要求


二、核心代码实现(Modbus RTU)

1. 串口通信基础类

using System;
using System.IO.Ports;

public class DeltaPLC
{
    private SerialPort _serialPort;
    private byte _stationAddress = 1; // 默认站号

    public void Connect(string portName)
    {
        _serialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One);
        _serialPort.DataReceived += SerialPort_DataReceived;
        _serialPort.Open();
    }

    private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
    {
        byte[] buffer = new byte[_serialPort.BytesToRead];
        _serialPort.Read(buffer, 0, buffer.Length);
        ProcessReceivedData(buffer);
    }

    private void ProcessReceivedData(byte[] data)
    {
        // 解析Modbus RTU帧(需实现CRC校验)
        // 示例:处理写线圈响应
        if (data[1] == 0x05) 
        {
            bool coilStatus = data[3] == 0xFF;
            Console.WriteLine($"线圈状态更新: {(coilStatus ? "ON" : "OFF")}");
        }
    }
}

2. Modbus功能实现

public class ModbusRTU
{
    // 读取保持寄存器(功能码03)
    public ushort[] ReadHoldingRegisters(byte station, ushort startAddr, ushort count)
    {
        byte[] request = new byte[8]
        {
            station, 0x03, 
            (byte)(startAddr >> 8), (byte)startAddr,
            (byte)(count >> 8), (byte)count,
            0x00, 0x00
        };
        AddCRC(request);
        SendRequest(request);
        return ReadResponse<ushort>(4 + 2 * count);
    }

    // 写单个寄存器(功能码06)
    public void WriteSingleRegister(byte station, ushort addr, ushort value)
    {
        byte[] request = new byte[8]
        {
            station, 0x06,
            (byte)(addr >> 8), (byte)addr,
            (byte)(value >> 8), (byte)value,
            0x00, 0x00
        };
        AddCRC(request);
        SendRequest(request);
    }

    private void AddCRC(byte[] data)
    {
        ushort crc = CalculateCRC(data, data.Length);
        data[data.Length] = (byte)crc;
        data[data.Length + 1] = (byte)(crc >> 8);
    }

    private ushort CalculateCRC(byte[] data, int length)
    {
        ushort crc = 0xFFFF;
        for (int i = 0; i < length; i++)
        {
            crc ^= (ushort)data[i] << 8;
            for (int j = 0; j < 8; j++)
            {
                if ((crc & 0x8000) != 0)
                    crc = (ushort)((crc << 1) ^ 0xA001);
                else
                    crc <<= 1;
            }
        }
        return crc;
    }
}

三、工业级应用

1. 实时数据监控

public class PLCMonitor
{
    private DeltaPLC _plc;
    private Timer _timer;

    public PLCMonitor()
    {
        _plc = new DeltaPLC();
        _plc.Connect("COM3");
        
        _timer = new Timer(1000);
        _timer.Elapsed += (s, e) => 
        {
            ushort[] temps = _plc.ReadHoldingRegisters(1, 40001, 4); // 读取D40001-D40004
            UpdateDashboard(temps);
        };
        _timer.Start();
    }
}

2. 批量数据写入

public void BatchWriteDRegisters()
{
    ushort[] data = { 1000, 2000, 3000 };
    byte[] request = new byte[6 + 2 * data.Length];
    
    request[0] = _stationAddress;
    request[1] = 0x10; // 功能码16
    request[2] = 0x00; request[3] = 0x13; // 起始地址40001
    request[4] = 0x00; request[5] = 0x03; // 写入3个寄存器
    Buffer.BlockCopy(data, 0, request, 6, 2 * data.Length);
    AddCRC(request);
    _serialPort.Write(request, 0, request.Length);
}

参考项目 基于C#与台达PLC通讯例程 www.youwenfan.com/contentzhe/62524.html

四、调试 优化

1. 通信参数验证

# 使用串口助手验证基础通信
$port = new-Object System.IO.Ports.SerialPort COM3,9600,None,8,one
$port.Open()
$port.WriteLine(":01030000000184") # 读取D0
$port.Close()

2. 异常处理机制

public ushort SafeReadHoldingRegister(ushort addr)
{
    try
    {
        return _plc.ReadHoldingRegisters(1, addr, 1)[0];
    }
    catch(ModbusException ex)
    {
        if(ex.ErrorCode == ModbusErrorCode.IllegalAddress)
            Log.Error("非法寄存器地址");
        else if(ex.ErrorCode == ModbusErrorCode.Timeout)
            Reconnect();
        return 0;
    }
}

3. 性能优化方案


五、协议扩展

1. 自定义功能码支持

public class CustomModbus : ModbusRTU
{
    // 扩展读取PLC运行状态(自定义功能码0x10)
    public bool GetRunStatus()
    {
        byte[] response = SendCustomCommand(0x10, new byte[] { 0x00 });
        return response[3] == 0x01;
    }
}

2. 安全增强方案

// 添加AES加密
public byte[] EncryptData(byte[] data)
{
    using (Aes aes = Aes.Create())
    {
        aes.Key = _aesKey;
        aes.IV = _aesIV;
        return aes.CreateEncryptor().TransformFinalBlock(data, 0, data.Length);
    }
}

六、工程部署

  1. 硬件选型

    • 串口服务器:MOXA CP-114UE(支持Modbus TCP转发)
    • 工业PC:研华工控机AIMB-501(支持宽温运行)
  2. 安全配置

    // 启用Modbus安全认证
    _plc.Security = new ModbusSecurity
    {
        Username = "admin",
        Password = "SecurePass123!",
        Encryption = ModbusSecurity.EncryptionType.AES128
    };
    
  3. 监控方案

    • 使用Modbus Poll验证基础通信
    • 通过Wireshark抓包分析数据帧
    • 部署OPC UA网关实现跨平台集成

 

专注于matlab/simulink,电子电路,编程