C#和NModbus库实现Modbus从站

C#和NModbus库实现Modbus从站,支持自定义地址范围(如0-34)的寄存器配置


一、核心代码实现

csharp 复制代码
using System;
using System.IO.Ports;
using NModbus;
using NModbus.Serial;

class ModbusRtuSlaveConfigurable
{
    private static SerialPort _serialPort;
    private static IModbusSlaveNetwork _slaveNetwork;
    private static ushort _startAddress = 0;  // 起始地址
    private static ushort _endAddress = 34;   // 结束地址(含)

    static void Main(string[] args)
    {
        // 1. 配置串口参数
        _serialPort = new SerialPort {
            PortName = "COM3",
            BaudRate = 9600,
            Parity = Parity.None,
            DataBits = 8,
            StopBits = StopBits.One
        };

        // 2. 创建Modbus工厂和适配器
        var factory = new ModbusFactory();
        var adapter = new SerialPortAdapter(_serialPort);

        // 3. 创建从站网络
        _slaveNetwork = factory.CreateSlaveNetwork(adapter);

        // 4. 创建从站实例(Slave ID=1)
        var slave = factory.CreateSlave(unitId: 1);

        // 5. 配置数据存储区(支持0x03读保持寄存器、0x01读线圈)
        ConfigureDataStores(slave);

        // 6. 启动监听
        _slaveNetwork.AddSlave(slave);
        _slaveNetwork.ListenAsync();

        Console.WriteLine($"Modbus RTU从站已启动 (ID=1, 地址范围 {0}-{1}),按Enter退出...", _startAddress, _endAddress);
        Console.ReadLine();

        // 7. 清理资源
        _serialPort.Close();
        _slaveNetwork.Dispose();
    }

    static void ConfigureDataStores(IModbusSlave slave)
    {
        // 保持寄存器(地址0-34,共35个)
        slave.DataStore.HoldingRegisters.StorageOperationOccurred += (sender, e) => {
            Console.WriteLine($"[{DateTime.Now}] 寄存器 {e.StartingAddress} 被操作: {e.Operation}");
        };
        InitializeRegisters(slave.DataStore.HoldingRegisters);

        // 线圈(地址0-34,共35个)
        slave.DataStore.CoilDiscretes.StorageOperationOccurred += (sender, e) => {
            Console.WriteLine($"[{DateTime.Now}] 线圈 {e.StartingAddress} 被操作: {e.Operation}");
        };
        InitializeCoils(slave.DataStore.CoilDiscretes);
    }

    static void InitializeRegisters(ISlaveDataStore<ushort> registers)
    {
        // 初始化保持寄存器默认值(示例:地址0=温度,地址1=压力)
        registers[0] = 2500;    // 温度值(单位:0.1℃)
        registers[1] = 1200;    // 压力值(单位:0.1kPa)
        for (ushort i = 2; i <= _endAddress; i++) {
            registers[i] = 0;   // 其他寄存器初始化为0
        }
    }

    static void InitializeCoils(ISlaveDataStore<bool> coils)
    {
        // 初始化线圈默认值(示例:地址0=设备运行状态)
        coils[0] = true;        // 设备运行中
        for (ushort i = 1; i <= _endAddress; i++) {
            coils[i] = false;   // 其他线圈初始化为关闭
        }
    }
}

二、功能说明

1. 地址范围配置
  • 修改起始/结束地址 :调整_startAddress_endAddress变量即可改变有效地址范围(如0-100
  • 动态配置支持:可通过配置文件或命令行参数动态加载地址范围(见扩展部分)
2. 数据存储管理
存储类型 地址范围 数据类型 功能码 操作示例
保持寄存器 0x0000-0x0022 16位整数 0x03/0x06 读取温度值:03 03 00 00 00 01
离散输出(线圈) 0x0000-0x0022 布尔值 0x01/0x05 写入运行状态:05 01 00 00
3. 事件监控
  • 存储操作记录 :通过StorageOperationOccurred事件实时记录数据变化
  • 异常处理 :自动捕获无效地址访问并返回错误码(如03 03 02 00 0A表示地址越界)

三、扩展功能实现

1. 动态地址配置(通过配置文件)
csharp 复制代码
// app.config 添加配置项
<appSettings>
  <add key="StartAddress" value="0"/>
  <add key="EndAddress" value="34"/>
</appSettings>

// 读取配置
var startAddr = int.Parse(ConfigurationManager.AppSettings["StartAddress"]);
var endAddr = int.Parse(ConfigurationManager.AppSettings["EndAddress"]);
2. 自定义数据模拟
csharp 复制代码
// 模拟温度传感器数据变化(每秒更新)
Timer timer = new Timer(_ => {
    ushort temp = (ushort)(2000 + new Random().Next(100)); // 20.00~30.00℃
    slave.DataStore.HoldingRegisters[0] = temp;
}, null, 0, 1000);
3. 安全校验增强
csharp 复制代码
// 添加从站ID验证
if (request.UnitId != 1) 
{
    SendErrorResponse(request, 0x07); // 错误码07:从站ID不匹配
    return;
}

四、扩展资源

相关推荐
周周记笔记4 小时前
Python及Ipython解释器
开发语言·python
oioihoii4 小时前
当无符号与有符号整数相遇:C++中的隐式类型转换陷阱
java·开发语言·c++
猪哥-嵌入式5 小时前
Go语言实战教学:从一个混合定时任务调度器(Crontab)深入理解Go的并发、接口与工程哲学
开发语言·后端·golang
互联网中的一颗神经元5 小时前
小白python入门 - 6. Python 分支结构——逻辑决策的核心机制
开发语言·数据库·python
妄小闲5 小时前
企业网站模版 免费PHP企业网站源码模板
开发语言
AhriProGramming5 小时前
Python学习快速上手文章推荐(持续更新)
开发语言·python·学习·1024程序员节
IDOlaoluo5 小时前
nginx-1.9.1.tar.gz 安装教程(详细步骤,从解压到启动)
开发语言·python
赵杰伦cpp6 小时前
C++的继承机制精讲
java·开发语言·c++·后端
百花~7 小时前
JVM(Java虚拟机)~
java·开发语言·jvm