C#与台达PLC通信,整合了Modbus协议实现和工业级调试技巧,包含串口/以太网双模式支持
一、硬件配置要点
1. PLC参数设置(以DVP-ES3为例)
1. 通信接口配置:
- 串口模式:RS-485(需外接转换器)
- 波特率:9600(默认)
- 数据位:8
- 停止位:1
- 校验位:None
2. Modbus从站设置:
- 站号:1-247(需与上位机一致)
- 功能码支持:03(读保持寄存器)/06(写单个寄存器)/16(写多个寄存器)
2. 网络拓扑要求
- 物理层:Cat6网线(以太网模式)或MAX485转换器(串口模式)
- 协议层:Modbus RTU/TCP
- 防火墙:开放502端口(以太网)
二、核心代码实现(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. 性能优化方案
-
缓冲区管理:预分配2KB接收缓冲区
-
异步操作:
public async Task<ushort[]> ReadAsync(ushort addr, ushort count) { return await Task.Run(() => ReadHoldingRegisters(addr, count)); } -
连接池:维护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);
}
}
六、工程部署
-
硬件选型:
- 串口服务器:MOXA CP-114UE(支持Modbus TCP转发)
- 工业PC:研华工控机AIMB-501(支持宽温运行)
-
安全配置:
// 启用Modbus安全认证 _plc.Security = new ModbusSecurity { Username = "admin", Password = "SecurePass123!", Encryption = ModbusSecurity.EncryptionType.AES128 }; -
监控方案:
- 使用Modbus Poll验证基础通信
- 通过Wireshark抓包分析数据帧
- 部署OPC UA网关实现跨平台集成