CSoft.Protocol.Modbus 11.0.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package CSoft.Protocol.Modbus --version 11.0.0
                    
NuGet\Install-Package CSoft.Protocol.Modbus -Version 11.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CSoft.Protocol.Modbus" Version="11.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CSoft.Protocol.Modbus" Version="11.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CSoft.Protocol.Modbus" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CSoft.Protocol.Modbus --version 11.0.0
                    
#r "nuget: CSoft.Protocol.Modbus, 11.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CSoft.Protocol.Modbus@11.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CSoft.Protocol.Modbus&version=11.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CSoft.Protocol.Modbus&version=11.0.0
                    
Install as a Cake Tool

Modbus 协议库

CSoft.Protocol.Modbus 提供 Modbus 主站和从站,支持 RTU 和 Modbus TCP 报文、寄存器与线圈读写,以及基于 [CHProtocol] 的模型映射。

安装与兼容性

dotnet add package CSoft.Protocol.Modbus

11.0.0 新增 net11.0 程序集,同时提供 netstandard2.0、net8.0、net9.0 和 net10.0 程序集。新部署可使用 .NET 10 或 .NET 11,.NET 8 和 .NET 9 目标供现有应用兼容使用。 .NET 支持周期

主站快速开始

下面的示例连接到本机的 Modbus TCP 从站,读取单元标识 1 的第一个保持寄存器。可以使用后面的 TCP 从站示例配对运行。

using System;
using Modbus;

var master = ModBusMaster.UseTcp("127.0.0.1", 1502)
    .Protocol(ModbusType.TCP)
    .Timeout(3000)
    .Build();

try
{
    await master.OpenAsync();
    var registers = await master.ReadHoldingRegistersAsync(0x01, start: 0, count: 1);
    Console.WriteLine(registers[0]);
}
finally
{
    await master.CloseAsync();
}

使用串口时,将主站构造替换为下面的写法。默认串口参数是 9600 波特、8 数据位、无校验、1 停止位。

var master = ModBusMaster.UseSerial("COM2", baudRate: 9600).Build();

UseTcp、UseSerial 和 UseNamedPipe 选择物理链路。报文格式默认是 RTU,即使使用 TCP 链路也是如此。设备使用带 MBAP 头的 Modbus TCP 报文时,指定 .Protocol(ModbusType.TCP)。也可以通过 new ModBusMaster(physicalPort, ModbusType.TCP) 使用已有的 IPhysicalPort。

主站的读写方法接受 byte 站号,也接受十进制字符串 "1"、"01" 和带 0x 前缀的十六进制字符串 "0x01"。start、register、coil 和 [CHProtocol] 中的地址是从 0 开始的协议地址。如果设备手册将首个保持寄存器标为 40001,通常传入 0,具体以设备地址表为准。

功能码

功能码 主站方法 数据区
FC01 ReadCoilsAsync 读线圈,返回 bool[]
FC02 ReadDiscreteInputsAsync 读离散量输入,返回 bool[]
FC03 ReadHoldingRegistersAsync 读保持寄存器,返回 ushort[]
FC04 ReadInputRegistersAsync 读输入寄存器,返回 ushort[]
FC05 WriteCoilAsync 写单个线圈
FC06 WriteRegisterAsync 写单个保持寄存器
FC15 WriteCoilsAsync 写多个线圈
FC16 WriteRegistersAsync 写多个保持寄存器

批量操作超出单帧上限时会自动拆分。单帧最多读取 125 个寄存器或 2000 个位,写入 123 个寄存器或 1968 个线圈。

模型映射

用 [CHProtocol] 标注属性的起始寄存器。GetAsync<T> 使用 FC03 读取保持寄存器,并将值填入模型。SetAsync<T> 使用 FC16 写入模型中所有非 null 的映射属性,数值类型的默认值也会写入。

using Modbus;

public class SensorData
{
    [CHProtocol(1)]
    public float Temperature { get; set; }

    [CHProtocol(3)]
    public ushort Humidity { get; set; }

    [CHProtocol(5)]
    public float Pressure { get; set; }

    [CHProtocol(7, count: 4)]
    public string DeviceName { get; set; } = string.Empty;

    [CHProtocol(11)]
    public bool Running { get; set; }
}

在主站连接打开后读写模型。

var data = await master.GetAsync<SensorData>(0x01);

await master.SetAsync(0x01, new SensorData
{
    Temperature = 25.5f,
    Humidity = 60,
    Pressure = 101.3f,
    DeviceName = "PUMP-A",
    Running = true
});

读写时会合并连续的寄存器,并按单帧上限拆分。读取可用 master.MaxMergeGap 跨过小间隙,前提是设备允许读取间隙里的地址。默认值 0 只合并连续块。也可以用 BlockList.From<SensorData>(maxMergeGap: 2) 生成块列表,再传给 GetAsync(address, blocks)。无块参数的非泛型 GetAsync(address) 使用 master.BlockInfos。

数据类型

C# 类型 寄存器数 说明
ushort、short 1 16 位整数
uint、int、float 2 32 位值
double 4 64 位浮点数
bool 1 写入 0 或 1,读取时非零为 true
string N 用 [CHProtocol(address, count: N)] 声明长度

字序与字符串

主站用 ReqWordOrder 设置写入值的字序,用 RspWordOrder 设置读取值的字序。从站通过 ModBusSlaveOptions.WordOrder 配置模型映射。默认均为 ABCD。

WordOrder 32 位值 0x12345678 的线上字节
ABCD 12 34 56 78
DCBA 78 56 34 12
CDAB 56 78 12 34
BADC 34 12 78 56

手动构建 BlockList 时,可通过 Channel.IsHighByteBefore 为单个通道覆盖读取字序。true 使用 ABCD,false 使用 DCBA,null 使用主站的 RspWordOrder。旧版主站配置 IsHighByteBefore_Req 和 IsHighByteBefore_Rsp 映射到对应字序。IsHighByteBefore_MBAP 控制 TCP 报文头字段的字节序,标准 Modbus TCP 使用默认值 true。

字符串默认用 ASCII,可通过主站的 StringEncoding 和从站的 ModBusSlaveOptions.StringEncoding 配置。N 个寄存器能存放 2 × N 个编码后的字节。写入时不足部分补 0x00,超长会抛出 InvalidOperationException。读取时去掉尾部的空字符。

从站快速开始

从站提供 HoldingRegisters、InputRegisters、Coils 和 DiscreteInputs 四个数据区。主站可以读写保持寄存器和线圈,读取输入寄存器和离散量输入。应用可以直接访问这四个数组。下面的示例在本机启动 TCP 从站,响应会发回请求来源客户端。

using System;
using CommBuilder;
using Modbus;

var server = Comm.TopServer()
    .UseTcpServer("127.0.0.1", 1502)
    .WithParserFactory(ModBusSlave.CreateParser)
    .Build();

using var slave = new ModBusSlave(server, new ModBusSlaveOptions
{
    Address = 0x01,
    ModbusType = ModbusType.TCP
});

slave.HoldingRegisters[0] = 0x1234;
slave.WriteReceived += write =>
    Console.WriteLine($"收到 FC{write.FunctionCode:X2} 写入,起始地址 {write.StartAddress}");

try
{
    await slave.StartAsync();
    Console.WriteLine("从站已启动,按 Enter 停止。");
    Console.ReadLine();
}
finally
{
    await slave.StopAsync();
}

使用串口时,可用 new ModBusSlave(new Communication.Bus.PhysicalPort.SerialPort("COM3", 9600)) 创建 RTU 从站,并使用同样的 StartAsync 和 StopAsync 管理连接。

对于进入请求处理阶段的单播帧,功能码不受支持、地址越界或数据非法时,从站会返回 Modbus 异常响应。RTU 地址 0 用于广播,有效的广播写请求会执行且不返回响应。WriteReceived 在成功写入后触发,包括广播写入。

绑定模型与自定义传输

BindModel 将模型属性映射到保持寄存器,并立即写入初始值。主站通过 FC06 或 FC16 更新保持寄存器后,从站会同步回模型。应用直接修改模型时,调用 SyncModelToRegisters() 发布新值。应用直接修改保持寄存器后,可调用 SyncRegistersToModel() 更新模型。

var model = new SensorData { Temperature = 25.5f, DeviceName = "PUMP-A" };
slave.BindModel(model);

model.Temperature = 30f;
slave.SyncModelToRegisters();

自定义传输可以用 new ModBusSlave(options) 创建从站核心,向 HandleRequest(frame) 传入完整报文。返回值是响应报文,或表示无需响应的 null。

分帧、超时与取消

RTU 分帧根据功能码和字节数推导长度,并校验 CRC。推导长度不匹配时,会尝试在候选长度中寻找 CRC 正确的帧。Modbus TCP 按 MBAP 长度域分帧。完整帧进入响应校验时,主站还会检查站号、功能码以及适用的事务 ID、数据长度或写回显。

异常 含义
ModbusSlaveException 从站返回协议异常响应,可读取 ExceptionCode 和 DeviceAddress
ModbusFrameException 响应的结构或字段与请求不匹配
ModbusCrcException 响应校验阶段检测到 RTU CRC 不符
ModbusTimeoutException 请求超时,未收到可供处理的响应
OperationCanceledException 调用者取消了等待

前四种异常位于 Modbus.Exceptions。损坏的 RTU 帧可能在分帧阶段被丢弃,此时主站可能收到超时异常。持续噪声超过分帧缓冲阈值时,分帧器会丢弃旧数据并保留一段尾部供下次解析。

CancellationToken 在提交请求前取消时可阻止提交。请求进入底层队列后,令牌只取消当前调用的等待,已经提交的请求仍可能发出并写入设备。

using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(2));
var data = await master.GetAsync<SensorData>(0x01, cts.Token);

主站提供 IsConnect 状态,以及 OnConnect、OnDisconnect、OnSentData、OnReceivedData 事件。

构建与测试

从源码构建需要 .NET 11 SDK。运行全部测试还需要安装 .NET 10 运行时。

dotnet build Modbus.sln -c Release
dotnet test Test/Test.csproj -c Release --no-build

Release 构建会在 Modbus/bin/Release 生成 NuGet 包。测试分别在 .NET 10 和 .NET 11 上运行。

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed.  net11.0 is compatible. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (7)

Showing the top 5 NuGet packages that depend on CSoft.Protocol.Modbus:

Package Downloads
CSoft.Protocol.FlueGasAnalyzer

杭州泽天春来烟气分析仪 Modbus RTU v6.3 协议

CSoft.Protocol.TPF146D

泽天温压流146D通讯协议

CSoft.Protocol.TPF113B

泽天温压流113B通讯协议

CSoft.Protocol.DustAnalyzerSampling

泽天抽取粉尘仪通讯协议

CSoft.Protocol.DustAnalyzerSquare

泽天方型粉尘仪通讯协议

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
11.0.1 57 11/13/2026
11.0.0 54 11/13/2026
10.100.0 108 10/29/2026
10.2.1 232 8/21/2026
10.2.0 169 5/28/2026
10.1.1 152 5/19/2026
10.1.0 152 5/11/2026
10.0.10 162 3/31/2026
10.0.9 155 3/30/2026
10.0.8 293 1/14/2026
10.0.7 230 1/14/2026
10.0.6 228 1/13/2026
10.0.5 219 1/13/2026
10.0.4 224 1/13/2026
10.0.3 229 1/9/2026
10.0.2 245 1/8/2026
10.0.1 198 1/8/2026 10.0.1 is deprecated because it has critical bugs.
10.0.0 415 11/12/2025 10.0.0 is deprecated because it has critical bugs.
9.3.2 387 8/5/2025 9.3.2 is deprecated because it has critical bugs.
9.3.1 401 7/29/2025 9.3.1 is deprecated because it has critical bugs.
Loading failed

新增 .NET 11 目标,保留 .NET Standard 2.0 和 .NET 8/9/10。升级 CSoft.Protocol 至 11.0.1,更新主站、从站、模型映射及异常处理文档。