一、基于HslCommunication库的串口通信示例
csharp
using HslCommunication;
using HslCommunication.Profinet.Melsec;
using System;
using System.Threading.Tasks;
public class MelsecPLC
{
private MelsecMcNet _plc;
public async Task ConnectAsync(string ipAddress, int port = 5000)
{
_plc = new MelsecMcNet(ipAddress, port);
var result = await _plc.ConnectServerAsync();
if (!result.IsSuccess)
{
throw new Exception($"连接失败: {result.Message}");
}
}
// 读取D寄存器(示例读取D0-D9)
public ushort[] ReadDRegisters(int startAddress, int count)
{
var result = _plc.Read("D" + startAddress, count);
return result.IsSuccess ? result.Content : new ushort[0];
}
// 写入单个D寄存器
public bool WriteDRegister(int address, ushort value)
{
var result = _plc.Write("D" + address, value);
return result.IsSuccess;
}
// 批量写入D寄存器
public bool WriteDBlock(int startAddress, ushort[] values)
{
return _plc.Write("D" + startAddress, values) is OperateResult<byte[]> { IsSuccess: true };
}
}
// 使用示例
var plc = new MelsecPLC();
await plc.ConnectAsync("192.168.1.100");
ushort[] data = plc.ReadDRegisters(0, 10);
plc.WriteDRegister(100, 1234);
二、基于AxActUtlTypeLib的TCP/IP通信示例
csharp
using System;
using System.Runtime.InteropServices;
using ActUtlTypeLib;
public class MelsecPLC
{
private AxActUtlType _axActUtlType;
public MelsecPLC()
{
_axActUtlType = new AxActUtlType();
((System.ComponentModel.ISupportInitialize)(_axActUtlType)).BeginInit();
Controls.Add(_axActUtlType);
}
public int Connect(string ipAddress, int station = 0)
{
_axActUtlType.ActLogicalStationNumber = station;
_axActUtlType.ActPassword = "";
return _axActUtlType.Open();
}
public short[] ReadWords(string address, int count)
{
short[] buffer = new short[count];
int result = _axActUtlType.ReadDeviceBlock2(address, count, out buffer[0]);
return result == 0 ? buffer : new short[0];
}
public bool WriteWords(string address, short[] values)
{
return _axActUtlType.WriteDeviceBlock2(address, values.Length, ref values[0]) == 0;
}
}
// 使用示例
var plc = new MelsecPLC();
int status = plc.Connect("192.168.1.100");
short[] data = plc.ReadWords("D0", 10);
plc.WriteWords("D100", new short[] { 100, 200 });
三、基于MC协议的TCP/IP通信示例
csharp
using System;
using System.Net.Sockets;
using System.Text;
public class McProtocolPLC
{
private TcpClient _client;
private NetworkStream _stream;
public bool Connect(string ip, int port = 5000)
{
_client = new TcpClient();
_client.Connect(ip, port);
_stream = _client.GetStream();
return _client.Connected;
}
// 构建读取帧(示例读取D0-D9)
private byte[] BuildReadFrame(string device, int startAddr, int count)
{
byte[] header = { 0x50, 0x00, 0x00, 0x03, 0xFF, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 };
byte[] cmd = { 0x01, 0x04 }; // 批量读取指令
byte[] addr = BitConverter.GetBytes(startAddr);
byte[] len = { (byte)(count & 0xFF), (byte)(count >> 8) };
byte[] devCode = GetDeviceCode(device);
using (MemoryStream ms = new MemoryStream())
{
ms.Write(header, 0, header.Length);
ms.Write(cmd, 0, cmd.Length);
ms.Write(addr, 0, addr.Length);
ms.Write(len, 0, len.Length);
ms.Write(devCode, 0, devCode.Length);
return ms.ToArray();
}
}
private byte[] GetDeviceCode(string device)
{
return device switch
{
"D" => new byte[] { 0xA8 },
"M" => new byte[] { 0x90 },
"X" => new byte[] { 0x9C },
"Y" => new byte[] { 0x9D },
_ => throw new ArgumentException("无效设备类型")
};
}
public ushort[] ReadData(string device, int startAddr, int count)
{
byte[] request = BuildReadFrame(device, startAddr, count);
_stream.Write(request, 0, request.Length);
byte[] response = new byte[1024];
int bytesRead = _stream.Read(response, 0, response.Length);
return ParseResponse(response, bytesRead);
}
private ushort[] ParseResponse(byte[] data, int length)
{
if (BitConverter.ToUInt16(data, 7) != 0x0000) // 检查结束码
throw new Exception("PLC返回错误");
int dataLength = (BitConverter.ToUInt16(data, 8) << 8) | data[9];
ushort[] result = new ushort[dataLength / 2];
for (int i = 0; i < result.Length; i++)
{
result[i] = (ushort)(data[10 + i * 2] | (data[11 + i * 2] << 8));
}
return result;
}
}
// 使用示例
var plc = new McProtocolPLC();
plc.Connect("192.168.1.100");
ushort[] data = plc.ReadData("D", 0, 10);
四、核心功能实现要点
-
地址转换规则
- 位地址:
Y7→37H→ ASCII码33 37 - 字地址:
D0→4000H→ ASCII码34 30 30 30
csharppublic static string DecimalToWordAddress(int address) { return (address * 2 + 4096).ToString("X4"); } - 位地址:
-
数据校验机制
csharpprivate byte CalculateChecksum(byte[] data) { byte sum = 0; foreach (byte b in data) { sum += b; } return (byte)(sum % 256); } -
异常处理策略
csharppublic async Task<OperateResult<byte[]>> SafeReadAsync(string address, int length) { try { return await ReadAsync(address, length); } catch (TimeoutException) { return OperateResult.Create<byte[]>(false, "通信超时"); } catch (Exception ex) { return OperateResult.Create<byte[]>(false, ex.Message); } }
五、完整项目结构建议
csharp
PLC_Communication/
├── MelsecPLC/ # 核心通信类
│ ├── MelsecPLC.cs # 主类
│ └── AddressConverter.cs # 地址转换工具
├── TestApp/ # 测试程序
│ ├── MainForm.cs # 主界面
│ └── PLCConfigForm.cs # 参数配置界面
└── Resources/ # 配置文件
└── plc_params.json # PLC参数存储
六、调试与优化建议
-
串口调试工具
使用
Putty或SecureCRT验证基础通信,设置参数:波特率:9600 | 数据位:7 | 停止位:1 | 校验:偶校验 -
性能监控
csharppublic class PerformanceMetrics { public long MessagesSent { get; set; } public long MessagesReceived { get; set; } public double CPUUsage { get; set; } public double MemoryUsage { get; set; } } -
日志记录
csharppublic static class Logger { public static void Log(string message) { File.AppendAllText("plc_log.txt", $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} - {message}{Environment.NewLine}"); } }
七、扩展功能实现
-
批量读写优化
csharppublic ushort[] ReadWords(string startAddr, int count) { string cmd = $"{STX}30{StationNumber}0400{startAddr}{count:X2}{ETX}"; var response = SendCommand(cmd); ushort[] result = new ushort[count]; for(int i=0; i<count; i++) { result[i] = (ushort)(response[5+2*i] * 256 + response[6+2*i]); } return result; } -
自动重连机制
csharppublic async Task AutoReconnectAsync() { while (!_isDisposed) { if (!_serialPort.IsOpen) { try { _serialPort.Open(); Debug.WriteLine("自动重连成功"); } catch (Exception ex) { Debug.WriteLine($"重连失败: {ex.Message}"); await Task.Delay(5000); } } await Task.Delay(1000); } }
参考代码 三菱通讯字节写入 www.youwenfan.com/contentcso/112220.html
八、推荐开发工具
| 工具名称 | 用途 | 下载地址 |
|---|---|---|
| GX Works3 | PLC程序编写与调试 | 三菱电机官网 |
| HslCommunication | 高级PLC通信库 | GitHub |
| Serial Port Monitor | 串口数据监控 | NirSoft官网 |