基于NModbus4库与松下PLC进行Modbus通信
一、硬件连接配置(参考)
-
RS485接线规范:
- PLC RS485端子:
+→ 驱动器+,-→ 驱动器- - 短接PLC的
E和-端子(部分型号需要)
- PLC RS485端子:
-
波特率拨码开关:
拨码位 1 2 3 4 波特率 9600 19200 38400 115200 数据位 8 8 8 8 停止位 1 1 1 1 校验位 None Even Odd Mark
二、松下PLC参数设置(参考)
-
系统寄存器配置:
地址 | 内容 | 说明 ---------------------------------- D1000 | 1 | 通信模式=Modbus RTU D1001 | 1 | 站号=1 D1002 | 9600 | 波特率 D1003 | 0 | 数据位=8 D1004 | 0 | 停止位=1 D1005 | 0 | 校验位=None -
通信指令配置:
|--[F145 SEND]--(DT10) // 从DT10发送数据到Modbus从站 |--[F146 RECV]--(DT20) // 接收Modbus从站数据到DT20
三、C#通信代码实现(基于NModbus4)
1. 基础通信类(ModbusPLC.cs)
using Modbus.Device;
using System;
using System.IO.Ports;
public class ModbusPLC
{
private IModbusMaster _master;
private SerialPort _serialPort;
public void Connect(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
{
_serialPort = new SerialPort(portName, baudRate, parity, dataBits, stopBits);
_serialPort.Open();
_master = ModbusSerialMaster.CreateRtu(_serialPort);
_master.Transport.ReadTimeout = 1000; // 1秒超时
_master.Transport.WriteTimeout = 1000;
}
public ushort[] ReadHoldingRegisters(byte slaveId, ushort startAddress, ushort numRegisters)
{
return _master.ReadHoldingRegisters(slaveId, startAddress, numRegisters);
}
public void WriteSingleCoil(byte slaveId, ushort coilAddress, bool value)
{
_master.WriteSingleCoil(slaveId, coilAddress, value);
}
public void Disconnect()
{
_master?.Dispose();
_serialPort?.Close();
}
}
2. 使用示例(Program.cs)
class Program
{
static void Main(string[] args)
{
var plc = new ModbusPLC();
try
{
plc.Connect("COM3", 9600, Parity.None, 8, StopBits.One);
// 读取保持寄存器(地址40001对应索引0)
ushort[] data = plc.ReadHoldingRegisters(1, 0, 10);
Console.WriteLine("读取数据: " + string.Join(", ", data));
// 写入单个线圈(地址0对应线圈1)
plc.WriteSingleCoil(1, 0, true);
}
finally
{
plc.Disconnect();
}
}
}
四、关键参数对照表
| Modbus地址 | NModbus索引 | 数据类型 | 松下PLC寄存器 |
|---|---|---|---|
| 40001 | 0 | UInt16 | D1000 |
| 40002 | 1 | UInt16 | D1001 |
| 030001 | 0 | UInt16 | A1000 |
| 110001 | 0 | Bool | C1000 |
五、异常处理与调试
-
常见错误代码:
InvalidOperationException:通信参数不匹配TimeoutException:超时(检查波特率/接线)IOException:端口被占用
-
调试工具推荐:
- Modbus Poll:测试寄存器读写
- WireShark:抓包分析通信流量
- PLC监控软件:查看实时寄存器状态
六、高级功能实现
1. 批量读写(示例)
// 读多个保持寄存器
ushort[] readData = plc.ReadHoldingRegisters(1, 0, 100);
// 写多个线圈
bool[] coilValues = Enumerable.Repeat(true, 16).ToArray();
plc.WriteMultipleCoils(1, 0, coilValues);
2. 异步通信
public async Task<ushort[]> AsyncReadHoldingRegisters(byte slaveId, ushort startAddr, ushort count)
{
return await Task.Run(() =>
_master.ReadHoldingRegisters(slaveId, startAddr, count));
}
参考代码 使用NMODBUS4开发的与松下PLC进行MODBUS通讯 www.youwenfan.com/contentcnr/112363.html
七、性能优化建议
- 连接池管理:复用SerialPort对象减少重连开销
- 数据缓存:对频繁读取的寄存器建立内存缓存
- 批量操作:合并多个写操作为单次请求
- CRC校验:启用硬件CRC加速(需支持CRC指令的PLC)
八、完整项目结构
├── ModbusPLC.sln
├── src/
│ ├── ModbusPLC.Core/ // 核心通信逻辑
│ ├── ModbusPLC.UI/ // 监控界面(WPF)
│ └── ModbusPLC.Tests/ // 单元测试
├── hardware/
│ └── PLC_Config.xlsm // PLC参数配置模板
└── docs/
└── Modbus地址对照表.xlsx