C# 与 PLC 进行 Modbus RTU 通讯的核心是通过串口(RS485/RS232)发送符合 Modbus 协议的报文,实现数据读写。以下是详细实现步骤、关键代码及注意事项:
一、前期准备
二、实现方式(推荐使用类库)
手动解析 Modbus 报文较繁琐,推荐使用成熟类库简化开发,常用类库:
三、完整代码示例(基于 NModbus4)
1. 安装 NModbus4
在 Visual Studio 中,通过 NuGet 安装 NModbus4:
bash
Install-Package NModbus4
2. 核心代码(读写示例)
csharp
using System;using System.IO.Ports;using Modbus.Device;class PlcModbusRtu{
static void Main(string[] args)
{
// 1. 配置串口参数(需与PLC一致)
string portName = "COM3"; // 串口名称(在设备管理器中查看)
int baudRate = 9600; // 波特率
Parity parity = Parity.None; // 校验位
int dataBits = 8; // 数据位
StopBits stopBits = StopBits.One; // 停止位
byte slaveAddress = 1; // PLC的Modbus从站地址
// 2. 初始化串口并连接
using (SerialPort serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits))
{
try
{
serialPort.Open();
if (!serialPort.IsOpen)
{
Console.WriteLine("串口打开失败!");
return;
}
// 3. 创建Modbus RTU主机
IModbusSerialMaster master = ModbusSerialMaster.CreateRtu(serialPort);
master.Transport.Retries = 3; // 通讯失败重试次数
master.Transport.ReadTimeout = 1000; // 读取超时时间(毫秒)
// 4. 读取PLC数据(示例:读取保持寄存器,地址0开始的2个寄存器)
// 寄存器地址:Modbus协议中地址从0开始,需与PLC侧寄存器地址对应
ushort startAddress = 0; // 起始地址
ushort numRegisters = 2; // 读取数量
ushort[] holdingRegisters = master.ReadHoldingRegisters(slaveAddress, startAddress, numRegisters);
Console.WriteLine($"读取保持寄存器:[{string.Join(", ", holdingRegisters)}]");
// 5. 向PLC写入数据(示例:向地址0写入单个寄存器)
ushort writevalue = 1234; // 写入值
master.WriteSingleRegister(slaveAddress, startAddress, writevalue);
Console.WriteLine($"向地址{startAddress}写入成功:{writevalue}");
// 6. 读取输入寄存器(如PLC的模拟量输入,地址10开始的1个)
ushort inputStartAddress = 10;
ushort[] inputRegisters = master.ReadInputRegisters(slaveAddress, inputStartAddress, 1);
Console.WriteLine($"读取输入寄存器(地址10):{inputRegisters[0]}");
}
catch (Exception ex)
{
Console.WriteLine($"通讯错误:{ex.Message}");
}
finally
{
if (serialPort.IsOpen)
serialPort.Close();
}
}
Console.ReadLine();
}}四、关键说明
五、调试工具
若通讯失败,可先用工具排查问题:

