C#编写ModbusTcp类库,模拟plc进行本地通信测试–往Modbus Slave写入数据
一、Modbus Slave 配置:
- 启动 Modbus Slave(如使用 Modbus Slave 模拟器)。下载地址: 模拟器下载地址
- 配置从站参数:
1.IP 地址:127.0.0.1(本地回环地址)。
2.端口:502(默认 Modbus TCP 端口)。
3.寄存器地址:例如保持寄存器(Holding Registers)的地址范围 0-100。
4.从站地址(Slave ID):通常为 1。
二、常用功能码:
- 03 功能码:读取保持寄存器(Read Holding Registers)。
- 06 功能码:写单个寄存器(Write Single Register)。
三、C# 项目依赖:
- 使用 System.Net.Sockets 实现 TCP 通信。
- 可以使用第三方库 NModbus 简化开发(可通过 NuGet 安装)。
四、C# 实现步骤:
- 使用 TcpClient 建立 TCP 连接。
- 构造 Modbus 请求报文并发送。
- 接收响应报文并解析数据。
- 处理异常和超时。
五、代码实现:
/// <summary>
/// 线圈写入
/// </summary>
/// <param name="address">写入地址</param>
/// <param name="value"></param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
public Result Write(string address, bool value, byte stationNumber = 1, byte functionCode = 5)
{
var result = new Result();
if (!socket?.Connected ?? true)
{
var conentResult = Connect();
if (!conentResult.IsSucceed)
return result.SetErrInfo(conentResult);
}
try
{
var chenkHead = GetCheckHead(functionCode);
var command = GetWriteCoilCommand(address, value, stationNumber, functionCode, chenkHead);
result.Requst = string.Join(" ", command.Select(t => t.ToString("X2")));
var sendResult = SendPackageReliable(command);
if (!sendResult.IsSucceed)
return result.SetErrInfo(sendResult).EndTime();
var dataPackage = sendResult.Value;
result.Response = string.Join(" ", dataPackage.Select(t => t.ToString("X2")));
if (chenkHead[0] != dataPackage[0] || chenkHead[1] != dataPackage[1])
{
result.IsSucceed = false;
result.Err = "响应结果校验失败";
socket?.SafeClose();
}
else if (ModbusHelper.VerifyFunctionCode(functionCode, dataPackage[7]))
{
result.IsSucceed = false;
result.Err = ModbusHelper.ErrMsg(dataPackage[8]);
}
}
catch (SocketException ex)
{
result.IsSucceed = false;
if (ex.SocketErrorCode == SocketError.TimedOut)
{
result.Err = "连接超时";
socket?.SafeClose();
}
else
{
result.Err = ex.Message;
}
}
finally
{
if (isAutoOpen) Dispose();
}
return result.EndTime();
}
/// <summary>
/// 写入
/// </summary>
/// <param name="address">写入地址</param>
/// <param name="values">写入字节数组</param>
/// <param name="stationNumber">站号</param>
/// <param name="functionCode">功能码</param>
/// <param name="byteFormatting">大小端设置</param>
/// <returns></returns>
public Result Write(string address, byte[] values,