基于C# 和 NModbus 库的 Modbus TCP 通信示例源码

基于 C# 和 NModbus 库Modbus TCP 通信示例源码,包含 客户端(Master)服务器端(Slave) 的实现,支持读写寄存器、线圈等操作。


一、环境准备

  1. NuGet 依赖安装

    在项目中安装 NModbus库(支持 .NET Framework 和 .NET Core):

    Install-Package NModbus
    
  2. 网络配置 Modbus TCP 默认端口为 502,需确保防火墙开放该端口。 从站地址(Unit ID)范围:1~247(默认 1)。


二、Modbus TCP 客户端(Master)示例

1. 同步读写操作

using System;
using System.Net.Sockets;
using Modbus.Device;

class ModbusTcpClientDemo
{
    static void Main()
    {
        string ipAddress = "192.168.1.100"; // 从站 IP
        int port = 502;                     // Modbus TCP 端口
        ushort unitId = 1;                // 从站地址

        using (TcpClient client = new TcpClient(ipAddress, port))
        {
            ModbusTcpMaster master = ModbusTcpMaster.CreateIp(client);

            try
            {
                // 读取保持寄存器(地址0,长度10)
                ushort startAddr = 0;
                ushort numRegs = 10;
                ushort[] registers = master.ReadHoldingRegisters(unitId, startAddr, numRegs);

                Console.WriteLine("读取保持寄存器结果:");
                for (int i = 0; i < registers.Length; i++)
                {
                    Console.WriteLine($"地址 {startAddr + i}: {registers[i]}");
                }

                // 写入单个寄存器(地址0,值1234)
                ushort writeAddr = 0;
                ushort writeValue = 1234;
                master.WriteSingleRegister(unitId, writeAddr, writeValue);
                Console.WriteLine($"写入寄存器 {writeAddr} 成功,值为 {writeValue}");

            }
            catch (Exception ex)
            {
                Console.WriteLine($"通信错误:{ex.Message}");
            }
        }
    }
}

2. 异步读写操作

using System;
using System.Net.Sockets;
using Modbus.Device;
using System.Threading.Tasks;

class ModbusTcpAsyncDemo
{
    static async Task Main()
    {
        string ipAddress = "192.168.1.100";
        int port = 502;
        ushort unitId = 1;

        using (TcpClient client = new TcpClient())
        {
            await client.ConnectAsync(ipAddress, port);
            ModbusTcpMaster master = ModbusTcpMaster.CreateIp(client);

            try
            {
                // 异步读取保持寄存器
                ushort startAddr = 0;
                ushort numRegs = 10;
                ushort[] registers = await master.ReadHoldingRegistersAsync(unitId, startAddr, numRegs);

                Console.WriteLine("异步读取结果:");
                foreach (var reg in registers)
                {
                    Console.Write(reg + " ");
                }

                // 异步写入多个线圈
                ushort startCoil = 0;
                bool[] coilValues = { true, false, true };
                await master.WriteCoilsAsync(unitId, startCoil, coilValues);

            }
            catch (Exception ex)
            {
                Console.WriteLine($"异步通信错误:{ex.Message}");
            }
            finally
            {
                client.Close();
            }
        }
    }
}

三、Modbus TCP 服务器端(Slave)示例

1. 基础服务器实现

using System;
using System.Net;
using System.Net.Sockets;
using Modbus.Device;
using Modbus.Utility;

class ModbusTcpSlaveDemo
{
    static void Main()
    {
        ushort slaveId = 1;        // 从站 ID
        int port = 502;            // 监听端口

        using (TcpListener listener = new TcpListener(IPAddress.Any, port))
        {
            listener.Start();
            Console.WriteLine($"Modbus TCP 从站已启动,监听端口 {port}...");

            ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveId, listener);
            slave.DataStore = DataStoreFactory.CreateDefaultDataStore(); // 初始化数据存储

            // 模拟数据更新(例如传感器数据)
            System.Timers.Timer timer = new System.Timers.Timer(1000);
            timer.Elapsed += (s, e) =>
            {
                ushort[] holdingRegs = slave.DataStore.HoldingRegisters;
                for (int i = 0; i < holdingRegs.Length; i++)
                {
                    holdingRegs[i] = (ushort)(i + (int)(DateTime.Now.Second * 0.5)); // 动态数据
                }
            };
            timer.Start();

            slave.Listen(); // 开始监听请求
            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
            slave.Stop();
        }
    }
}

2. 自定义数据处理(事件驱动)

using System;
using Modbus.Device;
using Modbus.Utility;

class CustomModbusSlave
{
    public static void Main()
    {
        ushort slaveId = 1;
        int port = 502;

        using (TcpListener listener = new TcpListener(IPAddress.Any, port))
        {
            listener.Start();
            ModbusSlave slave = ModbusTcpSlave.CreateTcp(slaveId, listener);
            slave.DataStore = DataStoreFactory.CreateDefaultDataStore();

            // 注册事件处理
            slave.ModbusSlaveRequestReceived += (sender, e) =>
            {
                Console.WriteLine($"收到请求:功能码 {e.Message.FunctionCode},地址 {e.Message.StartAddress},长度 {e.Message.Quantity}");
            };

            slave.Listen();
            Console.WriteLine("自定义从站运行中,按任意键退出...");
            Console.ReadKey();
            slave.Stop();
        }
    }
}

参考代码 modbus tcp通讯 示例源码 www.youwenfan.com/contentcnn/93804.html

四、关键功能说明

  1. 数据存储区 保持寄存器(Holding Registers):地址从 0 开始,用于存储可读写的 16 位数据(如传感器值)。 输入寄存器(Input Registers):地址从 0 开始,仅支持读取(如设备状态)。 线圈(Coils):布尔值(0/1),地址从 0 开始离散输入(Discrete Inputs):只读布尔值。
  2. 异常处理 捕获 ModbusSlaveException处理协议错误(如非法地址)。 设置超时时间:master.Transport.ReadTimeout = 3000;(单位:毫秒)。
  3. 性能优化 批量读写:使用 ReadMultipleRegistersWriteMultipleRegisters减少网络开销。 多线程处理:服务器端使用异步监听(async/await)提升并发能力。

五、测试工具推荐

  1. Modbus Poll(Windows) 功能:模拟主站,发送读写请求,验证从站响应。 下载地址:Modbus Poll /www.modbusdriver.com/software/modbus-poll.html)
  2. Modbus Slave(Windows) 功能:模拟从站,提供数据存储和响应。
posted @ 2025-12-17 15:44  yijg9998  阅读(23)  评论(0)    收藏  举报