CSoft.Protocol.Modbus 10.100.0

dotnet add package CSoft.Protocol.Modbus --version 10.100.0
                    
NuGet\Install-Package CSoft.Protocol.Modbus -Version 10.100.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="10.100.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CSoft.Protocol.Modbus" Version="10.100.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 10.100.0
                    
#r "nuget: CSoft.Protocol.Modbus, 10.100.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@10.100.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=10.100.0
                    
Install as a Cake Addin
#tool nuget:?package=CSoft.Protocol.Modbus&version=10.100.0
                    
Install as a Cake Tool

Modbus 协议库

一个简洁易用的 Modbus 通信库:主站 + 从站,Attribute 驱动的泛型数据映射、完整功能码支持、类型化异常。

  • 主站 + 从站:ModBusMaster 发起读写,ModBusSlave 应答请求,同一套 [CHProtocol] 模型
  • 报文格式与物理传输解耦:RTU / TCP 报文可跑在串口、TCP、命名管道任一传输上
  • 泛型映射:[CHProtocol] 标注模型属性,一行代码读写整个数据块
  • 功能码齐全:FC01 / 02 / 03 / 04 / 05 / 06 / 15 / 16
  • 快速分帧:按帧长驱动解析,帧完整即处理,无静默等待;噪声与残留自动恢复
  • 现场友好:四种字序(ABCD / DCBA / BADC / CDAB)、字符串编码可配
  • 现代 API:类型化异常、CancellationToken、自动拆包与合并

安装

dotnet add package CSoft.Protocol.Modbus

快速开始

1. 定义数据模型

public class SensorData
{
    [CHProtocol(1)]              // 寄存器地址 1(float 占 1、2 两个寄存器)
    public float Temperature { get; set; }

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

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

    [CHProtocol(7, count: 4)]    // string 必须声明寄存器个数(4 寄存器 = 8 字节)
    public string DeviceName { get; set; } = string.Empty;

    [CHProtocol(11)]             // bool 映射为单寄存器 0 / 1
    public bool Running { get; set; }
}

2. 建立连接

Builder 方式(推荐):

// 串口 + RTU(默认)
var master = ModBusMaster.UseSerial("COM2", baudRate: 9600).Build();
await master.OpenAsync();

// 网络 + TCP 报文格式
var master = ModBusMaster.UseTcp("192.168.1.100", 502)
    .Protocol(ModbusType.TCP)
    .Timeout(3000)               // 可选:请求超时(毫秒)
    .Build();

构造函数方式:

using Communication.Bus.PhysicalPort;

var master = new ModBusMaster(new TcpClient("192.168.1.100", 502), ModbusType.TCP);
await master.OpenAsync();

ModbusType 指的是报文格式,与物理链路无关:串口上可以跑 TCP 报文,网络上也可以跑 RTU 报文,按设备实际协议选择即可。

3. 读写数据

byte address = 0x01;

// 读:自动按地址合并相邻寄存器,通常一次请求拿回全部字段
var data = await master.GetAsync<SensorData>(address);
Console.WriteLine($"{data.Temperature}, {data.Humidity}, {data.DeviceName}");

// 写:连续地址的字段自动合并为一帧
await master.SetAsync(address, new SensorData
{
    Temperature = 25.5f,
    Humidity = 60,
    DeviceName = "PUMP-A",
    Running = true
});

地址支持字符串形式:"1"、"01"、"0x01" 均可。

功能码 API

除泛型模型外,也提供寄存器 / 线圈的原始读写:

方法 功能码 说明
ReadHoldingRegistersAsync(addr, start, count) FC03 读保持寄存器,返回 ushort[]
ReadInputRegistersAsync(addr, start, count) FC04 读输入寄存器,返回 ushort[]
ReadCoilsAsync(addr, start, count) FC01 读线圈,返回 bool[]
ReadDiscreteInputsAsync(addr, start, count) FC02 读离散量输入,返回 bool[]
WriteRegisterAsync(addr, register, value) FC06 写单个寄存器
WriteCoilAsync(addr, coil, value) FC05 写单个线圈
WriteRegistersAsync(addr, start, values) FC16 写多个寄存器
WriteCoilsAsync(addr, start, values) FC15 写多个线圈
var regs = await master.ReadHoldingRegistersAsync(0x01, start: 100, count: 10);
var coils = await master.ReadCoilsAsync(0x01, start: 0, count: 16);

await master.WriteRegisterAsync(0x01, register: 0x0064, value: 123);
await master.WriteCoilsAsync(0x01, start: 0, values: [true, false, true]);

超出单帧上限(读 125 / 写 123 个寄存器,读 2000 / 写 1968 个线圈)时自动拆分成多帧。

支持的数据类型

C# 类型 寄存器数 说明
ushort / short 1
uint / int / float 2 字序可配
double 4 字序可配
bool 1 0 / 1
string N 必须 [CHProtocol(..., count: N)]

字节序

多寄存器数值(float / int32 / double)的字节排列按设备现场情况选择,默认 ABCD(Modbus 标准大端):

master.ReqWordOrder = WordOrder.CDAB;   // 请求方向:交换 16 位字(常见于国产仪表的 float)
master.RspWordOrder = WordOrder.CDAB;   // 响应方向
WordOrder 线上字节(值 0x12345678) 常见场景
ABCD 12 34 56 78 标准 Modbus
DCBA 78 56 34 12 小端设备
CDAB 56 78 12 34 字交换,float 最常见
BADC 34 12 78 56 字节交换

单个属性也可用 [CHProtocol] 通道级覆盖(Channel.IsHighByteBefore)。

字符串编码

master.StringEncoding = Encoding.GetEncoding("GB2312");   // 默认 ASCII

写入时不足 count * 2 字节自动补 0x00;读取时自动截断尾部 \0。

异常处理

所有通信错误抛出 Modbus.Exceptions 下的类型化异常:

using Modbus.Exceptions;

try
{
    var data = await master.GetAsync<SensorData>(0x01);
}
catch (ModbusSlaveException ex)      // 从站返回异常响应
{
    Console.WriteLine($"异常码 {ex.ExceptionCode},地址 0x{ex.DeviceAddress:X2}");
    // ex.ExceptionCode: IllegalFunction / IllegalDataAddress / IllegalDataValue ...
}
catch (ModbusCrcException)           // RTU CRC 校验失败
{
}
catch (ModbusFrameException)         // 帧结构非法:事务 ID / 地址 / 功能码 / 字节数不符
{
}
catch (ModbusTimeoutException)       // 超时未收到有效响应
{
}

通信语义与健壮性

解析按帧长驱动:RTU 由功能码 + 字节数域推导帧长,TCP 由 MBAP 长度域确定,帧一完整即处理,不存在静默等待;帧长无法推导时按 CRC 校验滑窗判定。每帧进入数据映射前经过完整校验链:

CRC / MBAP → 从站地址 → 功能码 → 字节数 / 写回显 → 通道边界

任何一环不符都抛类型化异常——错误停在异常层,脏数据永远进不了模型。

常见异常现场的恢复行为:

情况 行为
线路噪声、上次残留的尾巴 不成帧的残字节随下一帧一起跳过,缓冲自动对齐
从站矮帧(字节数域虚高、数据少发) CRC 滑窗识别出真实帧长,立刻报结构错误,不等超时
从站无响应 / 响应损坏 请求超时抛 ModbusTimeoutException,重试即可,不影响后续
纯噪声持续灌入(错波特率等) 缓冲 4096 字节封顶,整段丢弃垃圾,不会无限增长

设计原则:任何单次异常只影响当次请求,不污染后续通信。

从机(ModBusSlave)

ModBusSlave 维护四个数据区(保持寄存器 / 输入寄存器 / 线圈 / 离散量输入), 应答主站的 FC01/02/03/04/05/06/15/16 请求,越界 / 非法值 / 未知功能码自动回异常响应, 支持 RTU 地址过滤与广播(地址 0 只执行写、不响应)。

建立从站

// 点对点(串口等)
var slave = new ModBusSlave(new SerialPort("COM3"), new ModBusSlaveOptions
{
    Address = 0x01,
    HoldingRegisterCount = 100,
    CoilCount = 64
});
await slave.StartAsync();

// TCP 服务端(多客户端,响应自动发回请求来源客户端)
var server = Comm.TopServer()
    .UseTcpServer("0.0.0.0", 502)
    .WithParserFactory(ModBusSlave.CreateParser)
    .Build();
var tcpSlave = new ModBusSlave(server, new ModBusSlaveOptions { Address = 0x01, ModbusType = ModbusType.TCP });
await tcpSlave.StartAsync();

数据区与事件

slave.HoldingRegisters[0] = 0x1234;     // 直接读写元素
slave.Coils[5] = true;

slave.WriteReceived += e =>             // 主站写入(含广播)后的回调
{
    Console.WriteLine($"主站写入 FC{e.FunctionCode:X2} 起始 {e.StartAddress}");
};

模型绑定

与主站共用同一个 [CHProtocol] 模型:绑定后主站读到的就是模型的值,主站写入自动同步回模型:

var model = new SensorData { Temperature = 25.5f, DeviceName = "PUMP-A" };
slave.BindModel(model);      // 模型 → 保持寄存器

model.Temperature = 30f;
slave.SyncModelToRegisters(); // 设备逻辑改模型后发布,主站即可读到

无传输核心

HandleRequest 与传输无关,一帧进一帧出(null 表示不响应),可直接用于测试或自定义传输:

var slave = new ModBusSlave(new ModBusSlaveOptions { Address = 0x01 });
byte[]? response = slave.HandleRequest(masterRequestFrame);

高级用法

手动构建 BlockList

var blockList = BlockList.From<SensorData>();
blockList.MaxMergeGap = 2;                  // 允许 2 个寄存器的缺口合并,减少往返
var channels = await master.GetAsync(0x01, blockList);

master.MaxMergeGap 对泛型读取同样生效(默认 0,仅合并完全连续的块)。

取消令牌

所有读写方法均接受 CancellationToken:

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

事件与状态

ModBusMaster 实现 IProtocol,具备 OpenAsync / CloseAsync / IsConnect 以及 OnConnect / OnDisconnect / OnSentData / OnReceivedData 事件。

配置项

属性 默认值 说明
ModbusType RTU 报文格式:RTU / TCP
ReqWordOrder / RspWordOrder ABCD 多寄存器数值字序
IsHighByteBefore_Req / _Rsp true 旧版字节序开关(映射到 WordOrder)
IsHighByteBefore_MBAP true MBAP 字段字节序(标准为大端)
StringEncoding ASCII string 通道编码
MaxMergeGap 0 读块合并允许的寄存器缺口
BlockInfos 空 无参 GetAsync(address) 使用的块定义
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. 
.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 (6)

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

Package Downloads
CSoft.Protocol.TPF146D

泽天温压流146D通讯协议

CSoft.Protocol.DustAnalyzerSampling

泽天抽取粉尘仪通讯协议

CSoft.Protocol.TPF113B

泽天温压流113B通讯协议

CSoft.Protocol.DustAnalyzerSquare

泽天方型粉尘仪通讯协议

CSoft.Protocol.DustAnalyzerCircular

泽天圆型粉尘仪通讯协议

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.100.0 50 10/29/2026
10.2.1 223 8/21/2026
10.2.0 167 5/28/2026
10.1.1 148 5/19/2026
10.1.0 149 5/11/2026
10.0.10 160 3/31/2026
10.0.9 153 3/30/2026
10.0.8 291 1/14/2026
10.0.7 228 1/14/2026
10.0.6 227 1/13/2026
10.0.5 217 1/13/2026
10.0.4 223 1/13/2026
10.0.3 228 1/9/2026
10.0.2 244 1/8/2026
10.0.1 197 1/8/2026 10.0.1 is deprecated because it has critical bugs.
10.0.0 414 11/12/2025 10.0.0 is deprecated because it has critical bugs.
9.3.2 386 8/5/2025 9.3.2 is deprecated because it has critical bugs.
9.3.1 399 7/29/2025 9.3.1 is deprecated because it has critical bugs.
9.3.0 683 7/24/2025 9.3.0 is deprecated because it has critical bugs.
9.2.5 1,083 7/23/2025 9.2.5 is deprecated because it has critical bugs.
Loading failed

添加从机