VspdCh340.Lib 1.2.2

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

VspdCh340.Lib - 虚拟串口数据转发类库

基于 com0com 驱动和 TLV 帧结构的多路串口数据转发系统。实现 CH340 USB 主串口与 12 个子虚拟串口(CNCB81-CNCB92)之间的双向数据透明传输。

功能特性

核心功能

  • 多路串口管理:同时管理 12 路虚拟串口(CNCB81-CNCB92)和 1 路 CH340 USB 主串口
  • 双向数据转发:支持从子串口到主串口,以及主串口到子串口的双向数据传输
  • 自动驱动安装:自动检测并安装 com0com 虚拟串口驱动,无需手动配置
  • 端口配置验证:安装前自动验证端口配置,避免重复安装
  • CH340 自动识别:通过特征匹配自动检测 CH340 USB 转串口设备
  • NuGet 包支持:封装为标准 NuGet 包,包含 MSBuild targets 自动部署驱动文件

数据链路层特性

  • TLV 帧结构:采用 SOF + TYPE + ADDR + LEN + DATA + CRC16 的 TLV 帧格式
  • 滑动窗口重同步:帧起始符(0xAA)自动定位,支持抗粘包/分段/干扰
  • CRC16-Modbus 校验:2 字节 CRC 校验确保数据完整性
  • 数据合并发送:支持超时合并和长度阈值合并,减少数据包数量

性能优化

  • 独立线程监听:每个串口分配独立监听线程,避免线程池资源竞争
  • 非阻塞 I/O:使用 RJCP.SerialPortStream 高性能串口库
  • 超时控制:50ms 读取超时,支持灵活的超时策略
  • 缓存队列保护:CDC 接收使用 8192 字节 FIFO 缓冲,防止数据丢失

可靠性保障

  • 线程安全设计:使用 Volatile.Read/WriteManualResetEventSlim 实现线程安全
  • 活动状态监测:通过 Stopwatch 监测 CDC 读写活动状态(200ms 超时判定)
  • 热插拔支持:驱动安装支持热插拔,无需重启系统
  • 自动重连:CDC 串口断开后自动重试扫描和重连

系统要求

  • Windows 10 / Windows 11 操作系统
  • .NET 10.0 或更高版本
  • CH340 USB 转串口设备(硬件模式)
  • 管理员权限(驱动安装必需)

安装和引用

方式 1:通过 NuGet 包管理器安装

<PackageReference Include="VspdCh340.Lib" Version="1.1.0" />

方式 2:项目引用

<ItemGroup>
  <ProjectReference Include="..\VspdCh340Lib\VspdCh340Lib.csproj" />
</ItemGroup>

自动部署功能

本 NuGet 包包含 VspdCh340.Lib.targets 文件,会在构建和发布时自动将 com0com 驱动文件复制到输出目录的 com0com 子文件夹中。VspdManager.Com0ComInstall() 方法可直接使用这些文件,无需额外配置。

基础用法

using VspdCh340.Lib;

var manager = new VspdManager();
manager.Start(Com0ComMode: true);

// 向 USB 主串口写入数据 (源端口 81, 数据)
manager.WritePack(81, data);

// 从指定端口读取数据 (超时 200ms)
var received = manager.ReadPack(81, 200);

manager.Stop();

核心 API

VspdManager
方法 说明
Start(bool Com0ComMode) 启动所有串口监听;Com0ComMode=true 时自动安装驱动并启用子串口转发
Stop() 停止所有串口监听并释放资源
WritePack(byte port, ReadOnlySpan<byte> data) 向 USB 主串口写入指定端口的数据(自动封装 TLV 帧)
ReadPack(byte port, int millisecondsTimeout) 从指定端口读取接收到的数据,支持超时等待
Com0ComInstall() 自动安装 com0com 虚拟串口驱动(静态方法)
属性 说明
IsOpen USB 主串口(CDC)是否已打开
ReadFlag USB 读操作活动标志(200ms 内有读操作为 true)
WriteFlag USB 写操作活动标志(200ms 内有写操作为 true)
ModbusRtu

Modbus RTU 协议封装类,支持通过 VspdManager 完成 Modbus 寄存器数据的收发。

方法 功能码 说明
ReadHoldingRegisters(byte port, byte id, ushort addr, ushort qty, int timeout) 0x03 读取保持寄存器
ReadInputRegisters(byte port, byte id, ushort addr, ushort qty, int timeout) 0x04 读取输入寄存器
WriteRegister(byte port, byte id, ushort addr, ushort value, int timeout) 0x06 写入单个保持寄存器
WriteRegisters(byte port, byte id, ushort addr, ReadOnlySpan<ushort> values, int timeout) 0x10 写入多个保持寄存器

参数说明:

  • port: 硬件串口号,有效范围 81-92
  • id: Modbus 从站地址,范围 1-247(0 为广播写)
  • addr: 寄存器起始地址
  • qty: 读取/写入数量(读寄存器:1-125;写多寄存器:1-123)
  • value/values: 要写入的寄存器值
  • timeout: 等待响应的超时时间(毫秒),默认 300

MbResult 返回值:

属性 说明
Success 通信及响应解析是否成功
ErrorCode Modbus 异常码;非异常响应为 0
Frame 从站返回的完整响应帧;超时或广播写入时为空数组
Registers 寄存器值数组;读寄存器时有效,写操作为空数组

使用示例:

using VspdCh340.Lib;

var manager = new VspdManager();
manager.Start(Com0ComMode: true);

var modbus = new ModbusRtu(manager);

// 读取保持寄存器 (端口81, 地址0, 数量10)
var result = modbus.ReadHoldingRegisters(81, 1, 0, 10);
if (result.Success)
{
    foreach (var reg in result.Registers)
        Console.WriteLine($"寄存器值: {reg}");
}

// 写入单个寄存器
var writeResult = modbus.WriteRegister(81, 1, 0, 0x1234);
if (writeResult.Success)
    Console.WriteLine("写入成功");

manager.Stop();

帧结构说明

本类库采用带起始符、不转义、纯字节流、滑动窗口重同步的帧结构设计,适配串口通信的抗粘包/分段/干扰需求。

帧格式

┌──────┬──────┬──────┬──────┬──────────┬────────┐
│ SOF  │ TYPE │ ADDR │ LEN  │  DATA[]  │  CRC16 │
│ 1B   │ 1B   │ 1B   │ 1B   │ 0–240B   │  2B    │
└──────┴──────┴──────┴──────┴──────────┴────────┘

帧顺序AA + TYPE + ADDR + LEN + DATA(≤240) + CRC16

字段语义

TLV 数据结构:本帧数据部分格式遵循CCITT(现 ITU-T)组织的 TLV(Type-Length-Value)编码原则。理论上ADDR应该在TYPE之前,但是为了与之前通信协议更好兼容,TYPE和ADDR保持当前位置。

字段 长度 说明
SOF 1B 帧起始字节,固定为 0xAA
TYPE 1B 业务类型/命令字标识,对应 TLV 的 T(Type)部分
ADDR 1B 从机地址,范围 81–82,0x00 用于广播,0xF0–0xFF 保留
LEN 1B DATA 长度,范围 0–240,不包含帧头和 CRC,对应 TLV 的 L(Length)部分
DATA 0–240B 不定长有效载荷,可裸传二进制数据,32bit 对齐(便于 32bit MCU 直接进行数据读写),对应 TLV 的 V(Value)部分
CRC16 2B 覆盖 SOF+TYPE+ADDR+LEN+DATA,小端序(低字节在前),CRC16-Modbus(多项式 0x8005,初始 0xFFFF)

设计要点

本设计依赖四条防线保证可靠性:

  1. SOF 起始符:固定 0xAA 作为帧同步标识,快速定位帧头
  2. LEN 硬截断:单帧数据最多 240B,不会"跑飞"
  3. ADDR 范围限制:仅 0x01–0xEF 有效,天然过滤非法帧
  4. CRC16 校验:覆盖整个帧内容,检测数据损坏

OSI 模型层次分析

本帧结构在国际标准化组织(ISO)的 OSI 七层模型中跨越多个层次,实现了从物理传输到应用协议的完整封装:

OSI 层次 对应实现 主要职责
物理层 (L1) RS-485/RS-232 串口 电信号传输、波特率配置、8N1 帧格式
数据链路层 (L2) SOF + CRC16 + 滑动重同步 帧封装/解封装、错误检测、帧同步
网络层 (L3) ADDR 从机地址判断或分发 节点寻址、广播支持
传输层 (L4) 按照 TLV 的 T 进行功能分发,LEN 长度控制 数据分发 、分段/重组 、流量(长度)控制
会话层 (L5) 未实现 本协议为简单串口数据,无需会话连接/断开管理
表示层 (L6) XOR 转码 (0x3E) 数据载荷使用固定密钥 XOR 0x3E 进行简单加密/解密
应用层 (L7) LEN + DATA (TLV的LV 结构) 业务命令的数据载荷处理
各层详细说明

1. 物理层 (Physical Layer)

  • 介质:RS-485 半双工 / RS-232 全双工 / 虚拟串口
  • 波特率:可配置(典型 9600/19200/115200)
  • 硬件:com0com 虚拟串口或物理串口适配器

2. 数据链路层 (Data Link Layer)

  • 帧同步0xAA 起始符快速定位帧边界
  • 数据长度:通过 LEN 字段计算帧总长度
  • 错误检测:CRC16-Modbus 覆盖完整帧
  • 滑动重同步:逐字节试探,失败仅丢弃 1 字节

3. 网络层 (Network Layer)

  • 单播:ADDR 0x01–0xEF(最多 239 个从机节点)
  • 广播:ADDR 0x00(所有节点接收处理)
  • 预留:ADDR 0xF0–0xFF(协议扩展、心跳、Bootloader)

4. 传输层 (Transport Layer)

  • 数据分发:根据 TLV 的 TYPE 字段将 DATA 分发到不同的业务处理模块
  • 长度限制:DATA 最大 240B,防止单帧过大

6. 表示层 (Presentation Layer)

  • XOR 转码:数据载荷使用固定密钥 0x3E 进行简单的 XOR 加密/解密
  • 加密方向
    • 发送时:原始数据 → XOR 0x3E → 传输
    • 接收时:传输数据 → XOR 0x3E → 原始数据
  • 特点:相同的密钥用于加密和解密,转码可逆

7. 应用层 (Application Layer)

  • 采用 TLV(Type-Length-Value)编码原则
  • 根据 L = LEN、V = DATA 进行数据载荷的处理
层次交互流程
应用层数据
    ↓ (TLV 编码的载荷)
表示层 XOR 0x3E 加密
    ↓ (转码处理)
传输层分段/TYPE重组
    ↓ (长度控制)
网络层寻址
    ↓ (ADDR 路由)
数据链路层帧封装
    ↓ (SOF + CRC)
物理层电信号传输
    ↓ (RS-485 差分信号)
物理层电信号接收
    ↓ (位同步)
数据链路层帧解封装 + CRC 校验
    ↓ (滑动重同步)
网络层地址过滤
    ↓ (ADDR 匹配)
传输层数据合并
    ↓ (TYPE匹配)
表示层 XOR 0x3E 解密
    ↓ (转码还原)
应用层数据

接收/重同步逻辑

采用 5 态状态机实现逐字节滑动重同步:

IDLE → GOT_SOF → GOT_TYPE → GOT_ADDR → GOT_LEN → GOT_DATA ──┐
   ↑                                                        │ CRC OK
   └────────────────────────────────── CRC FAIL / LEN 超界 ──┘
逐字节滑动重同步要点
状态 行为
IDLE 收到 0xAA → 进入 GOT_SOF;其他字节丢弃
GOT_SOF 下一字节作为 TYPE,进入 GOT_TYPE
GOT_TYPE 下一字节作为 ADDR,进入 GOT_ADDR
GOT_ADDR 下一字节作为 ADDR,进入 GOT_LEN
GOT_LEN 若 LEN > 240 → 滑动 1B,回到 IDLE 重新同步
GOT_DATA 收齐 LEN 字节后接收 2B CRC
CRC OK 交付帧,所有帧数据出队
CRC FAIL 仅丢弃 1 字节(原 SOF),窗口滑动重试

抗干扰设计

干扰类型 处理方式
粘包 SOF 定位帧头 + LEN + CRC 双重把关
分段 半包停在 GOT_DATA 等待后续数据,不丢失上下文
数据损坏 CRC16 校验失败时只丢弃 1 字节,自动重新同步
串行干扰 SOF + LEN 范围 + CRC 三重校验,干扰字节流中可自修复

优劣分析

维度 优点 缺点
性能 不转义,吞吐高、CPU 省、实现简单 CRC16 计算有一定开销
数据灵活性 DATA 可裸传二进制(结构体/图片碎片等)
可靠性 LEN 硬上限 240,单帧不会"跑飞" LEN 域被破坏时最多吞 245B
同步效率 有 SOF 起始符,首次同步快 数据中出现 0xAA 可能误触发同步
抗干扰 滑动 1B 重同步 + 三重校验,嘈杂环境表现优异 需完整接收一帧才能验证有效性
扩展性 ADDR 预留 0xFx 空间,TYPE 可扩展多种命令 帧格式固定,修改需两端同步

使用方法

  1. 引用 VspdCh340.Lib 类库
  2. 创建 VspdManager 实例并调用 Start(Com0ComMode: true) 启动
  3. 如需虚拟串口模式,类库会自动检测并安装 com0com 驱动
  4. 通过 WritePack() / ReadPack() 方法进行数据收发

虚拟串口配置

应用程序创建以下虚拟串口对,使用 PlugInMode 和 HiddenMode 优化配置:

端口 A 端口 B ADDR 值 配置 说明
COM81 CNCB81 0x51 (81) PlugInMode=yes, HiddenMode=yes UART 端口 1
COM82 CNCB82 0x52 (82) PlugInMode=yes, HiddenMode=yes UART 端口 2
COM83 CNCB83 0x53 (83) PlugInMode=yes, HiddenMode=yes UART 端口 3
COM84 CNCB84 0x54 (84) PlugInMode=yes, HiddenMode=yes UART 端口 4
COM85 CNCB85 0x55 (85) PlugInMode=yes, HiddenMode=yes UART 端口 5
COM86 CNCB86 0x56 (86) PlugInMode=yes, HiddenMode=yes UART 端口 6
COM87 CNCB87 0x57 (87) PlugInMode=yes, HiddenMode=yes UART 端口 7
COM88 CNCB88 0x58 (88) PlugInMode=yes, HiddenMode=yes MODBUS 端口 8
COM89 CNCB89 0x59 (89) PlugInMode=yes, HiddenMode=yes IIC 端口 9
COM90 CNCB90 0x5A (90) PlugInMode=yes, HiddenMode=yes SPI 端口 10
COM91 CNCB91 0x5B (91) PlugInMode=yes, HiddenMode=yes CAN2.0 端口 11
COM92 CNCB92 0x5C (92) PlugInMode=yes, HiddenMode=yes CAN2.0 端口 12
COM93 COM94 双向端口对(预留)
COM95 COM96 双向端口对(预留)

帧结构本应用中的实现说明

TYPE 字段(0xDF):标识 COM 端口转发协议,便于多协议混合场景识别。

ADDR 字段:直接映射到监听的 12 个虚拟串口(CNCB81-CNCB92),值为 81-92。

帧格式示例

当从 CNCB81(ADDR=81)收到 3 字节数据 0x11 0x22 0x33 时,转发到 USB 主串口的帧为:

AA DF 51 03 11 22 33 [CRC低字节] [CRC高字节]
↑  ↑  ↑  ↑  └─数据─┘
│  │  │  └── LEN=3
│  │  └── ADDR=81 (CNCB81)
│  └── TYPE=0xDF (COM转发协议)
└── SOF=0xAA

核心类说明

类名 职责 关键字段
VspdManager 串口管理和数据转发核心 subPorts[12] (子串口数组), cdcPort (CH340 USB端口), readBufs[12] (接收缓冲区), readEvents[12] (事件通知), cdcReadSw/cdcWriteSw (活动监测)
ModbusRtu Modbus RTU 协议门面类 uart (VspdManager 实例), 支持功能码 03/04/06/10
NcBus NC 总线协议封装 vspdManager (VspdManager 实例)

数据流向

┌─────────────────────────────────────────────────────────────────┐
│              子串口 → USB 主串口 (Write 路径)                     │
│                                                                 │
│  CNCB81-CNCB92 → 独立监听线程 → 数据合并 → TLV 帧封装            │
│                                                          ↓       │
│                                              CH340 USB 主串口    │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│              USB 主串口 → 子串口 (Read 路径)                     │
│                                                                 │
│  CH340 USB 主串口 → FIFO 缓冲队列 → 帧解析 + CRC 校验            │
│                                                          ↓       │
│                                              CNCB81-CNCB92      │
│                                                    ↓            │
│                                          数据载荷分发到目标端口   │
└─────────────────────────────────────────────────────────────────┘

技术栈

  • 目标框架: net10.0-windows
  • 语言: C# (latest)
  • 虚拟串口驱动: com0com
  • 串口通信库: RJCP.SerialPortStream (子串口), UartCtl (CH340 USB)
  • CRC 校验: CRC16-Modbus
  • 依赖项:
    • RJCP.SerialPortStream 3.0.5
    • UartCtl 4.0.0

串口库选择说明

本项目舍弃了 .NET 自带的 System.IO.Ports.SerialPort 库,主要原因是:

  • 无法打开特殊名称的串口System.IO.Ports 对串口名称有严格限制,无法正确识别和打开 CNCB81-CNCB92 这类特殊命名的虚拟串口
  • 兼容性问题System.IO.Ports 在处理 com0com 创建的虚拟串口时存在兼容性问题

许可证

本项目使用 MIT 许可证。

注意:本项目包含 com0com 驱动,该驱动采用 GPL 许可证分发。详见 com0com 许可证

免责声明

本应用程序会安装设备驱动并修改系统设置。请自行承担使用风险。运行前建议备份系统。

Product Compatible and additional computed target framework versions.
.NET net10.0-windows7.0 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.2.2 87 9/1/2026
1.1.0 92 8/24/2026