NModbus库
in C# with 0 comment

记录一下基本用法
NModbus版本 最新稳定版 3.91.2024.1031
NModbus.Serial 最新稳定版 3.0.81
英文文档

做主站

Modbus TCP

// 连接本机的Modbus从站
using var client = new TcpClient("127.0.0.1", 502);
var factory = new ModbusFactory();
var master = factory.CreateMaster(client);

byte slaveId = 1; // 从站地址
ushort startAddress = 0; // 起始地址
ushort numInputs = 5; // 读取5个寄存器

ushort[] inputs = master.ReadHoldingRegisters(slaveId, startAddress, numInputs);

Console.WriteLine("读取的输入寄存器数据:");
for (int i = 0; i < inputs.Length; i++) {
  Console.WriteLine($"寄存器 {startAddress + i} = {inputs[i]}");
  Thread.Sleep(500);
}

Modbus RTU

using NModbus;
using NModbus.Serial;
using System.IO.Ports;
class Program
{
    static void Main(string[] args)
    {
        using (SerialPort port = new SerialPort("COM10")) {
            // 配置
            port.BaudRate = 9600;
            port.DataBits = 8;
            port.Parity = Parity.None;
            port.StopBits = StopBits.One;
            port.ReadTimeout = 1000;
            port.WriteTimeout = 1000;
            port.Open();

            var factory = new ModbusFactory();
            IModbusMaster master = factory.CreateRtuMaster(port);

            byte slaveId = 1;
            ushort startAddress = 0;
            ushort[] registers = new ushort[] { 1, 2, 3 };

            // 操作寄存器
            //master.WriteMultipleRegisters(slaveId, startAddress, registers);
            ushort[] reg = master.ReadHoldingRegisters(slaveId, startAddress, 3);
            Console.WriteLine(string.Join(" ", reg));
        }

    }
}

做从站

Modbus TCP

using NModbus;
using NModbus.Data;
using System;
using System.Net;
using System.Net.Sockets;
 
namespace ModbusSlaveTest
{
    internal class Program
    {
        static void Main(string[] args)
        {
            //设置从站ID和端口
            byte slaveId = 1;
            int port = 502;
            //创建并配置监听TCP客户端的TcpListener
            var listener = new TcpListener(new IPAddress(new byte[] { 127, 0, 0, 1 }), port);
            listener.Start();
            //创建从站并开启监听
            var factory = new ModbusFactory();
            var modbusTcpSlaveNetwork = factory.CreateSlaveNetwork(listener);
            // 也可以绑定事件
            SlaveDataStore slaveDataStore = new SlaveDataStore();
            slaveDataStore.HoldingRegisters.BeforeWrite += (sender, arg) => {
                Console.WriteLine($"StartAddress:{arg.StartAddress}  data:{string.Join(" ", arg.Points)}");
            };
            var slave = factory.CreateSlave(slaveId, slaveDataStore);
            modbusTcpSlaveNetwork.AddSlave(slave);
            modbusTcpSlaveNetwork.ListenAsync();
            //输入寄存器
            slave.DataStore.InputRegisters.WritePoints(0, new ushort[] { 1, 2, 3 });
            //保持寄存器
            slave.DataStore.HoldingRegisters.WritePoints(0, new ushort[] { 3, 2, 1 });
            //线圈
            slave.DataStore.CoilDiscretes.WritePoints(0, new bool[] { true, false, true });
            //离散输入
            slave.DataStore.CoilInputs.WritePoints(0, new bool[] { true, true, true });

            Console.ReadKey();
        }

    }
}

Modbus RTU

using (SerialPort slavePort = new SerialPort(PrimarySerialPortName))
    {
        // configure serial port
        slavePort.BaudRate = 9600;
        slavePort.DataBits = 8;
        slavePort.Parity = Parity.None;
        slavePort.StopBits = StopBits.One;
        slavePort.Open();

        var factory = new ModbusFactory();
        var slaveNetwork = factory.CreateRtuSlaveNetwork(slavePort);

        IModbusSlave slave1 = factory.CreateSlave(1);
        IModbusSlave slave2 = factory.CreateSlave(2);

        slaveNetwork.AddSlave(slave1);
        slaveNetwork.AddSlave(slave2);

        slaveNetwork.ListenAsync().GetAwaiter().GetResult();
    }
}

带有回调的从站

using (SerialPort slavePort = new SerialPort("COM21")) {
    // configure serial port
    slavePort.BaudRate = 9600;
    slavePort.DataBits = 8;
    slavePort.Parity = Parity.None;
    slavePort.StopBits = StopBits.One;
    slavePort.Open();

    var factory = new ModbusFactory();
    var slaveNetwork = factory.CreateRtuSlaveNetwork(slavePort);
    byte slaveId = 1;
    SlaveDataStore slaveDataStore = new SlaveDataStore();
    slaveDataStore.HoldingRegisters.BeforeWrite += (sender, arg) => {
        Console.WriteLine(value: $"StartAddress:{arg.StartAddress}  data:{string.Join(" ", arg.Points)}");
    };
    IModbusSlave slave1 = factory.CreateSlave(slaveId, slaveDataStore);

    slaveNetwork.AddSlave(slave1);

    slaveNetwork.ListenAsync().GetAwaiter().GetResult();
}