C#实现USB数据收发

简介: C#实现USB数据收发

一、技术选型对比

库名称 适用场景 优势 局限性
LibUsbDotNet 通用USB设备通信 跨平台支持,API完善 需要安装libusb驱动
HidSharp HID类设备(键盘/鼠标等) 封装简单,支持异步通信 仅限HID协议设备
Windows API 定制化USB开发 直接操作底层接口 代码复杂度高

二、核心实现方案(基于LibUsbDotNet)

1. 设备枚举与连接

using LibUsbDotNet;
using LibUsbDotNet.Main;

public class UsbService {
   
    private UsbDevice _device;
    private UsbEndpointReader _reader;
    private UsbEndpointWriter _writer;

    // 初始化设备
    public bool Connect(int vid, int pid) {
   
        var finder = new UsbDeviceFinder(vid, pid);
        _device = UsbDevice.OpenUsbDevice(finder);

        if (_device == null) return false;

        try {
   
            _device.Open();
            IUsbDevice wholeDevice = _device as IUsbDevice;
            if (wholeDevice != null) {
   
                wholeDevice.SetConfiguration(1);
                wholeDevice.ClaimInterface(0);
            }

            _reader = _device.OpenEndpointReader(ReadEndpointID.Ep01);
            _writer = _device.OpenEndpointWriter(WriteEndpointID.Ep01);
            return true;
        } catch {
   
            _device.Close();
            return false;
        }
    }

    // 断开连接
    public void Disconnect() {
   
        _reader?.Dispose();
        _writer?.Dispose();
        _device?.Close();
        UsbDevice.Exit();
    }
}

2. 数据传输实现

// 同步发送数据
public int SendData(byte[] data) {
   
    int bytesWritten;
    ErrorCode ec = _writer.Write(data, 1000, out bytesWritten);
    return ec == ErrorCode.None ? bytesWritten : -1;
}

// 同步接收数据
public byte[] ReceiveData() {
   
    byte[] buffer = new byte[1024];
    int bytesRead;
    ErrorCode ec = _reader.Read(buffer, 5000, out bytesRead);
    return ec == ErrorCode.None ? buffer.Take(bytesRead).ToArray() : null;
}

// 异步接收(推荐)
public async Task<byte[]> AsyncReceive() {
   
    var buffer = new byte;
    var readTask = _reader.ReadAsync(buffer, 5000);
    await readTask.ConfigureAwait(false);
    return readTask.Result.Length > 0 
        ? readTask.Result.Take(readTask.Result.Length).ToArray() 
        : null;
}

三、高级功能实现

1. 控制传输(配置设备)

public void SendControlCommand(byte requestType, byte request, ushort value, ushort index, byte[] data) {
   
    int transferred;
    _device.ControlTransfer(
        (LibUsbDotNet.Main.ControlTransferFlags)requestType,
        request,
        value,
        index,
        data,
        data.Length,
        out transferred,
        5000);
}

2. 批量传输(高速数据)

// 配置批量端点
public void ConfigureBulkTransfer() {
   
    var deviceDesc = _device.DeviceDescriptor;
    _writer = _device.OpenEndpointWriter(
        ReadEndpointID.Ep02, // 批量输入端点
        512,                 // 最大包尺寸
        EndpointDirection.In);
}

// 执行批量传输
public int BulkWrite(byte[] data) {
   
    int bytesWritten;
    _writer.Write(data, 1000, out bytesWritten);
    return bytesWritten;
}

四、工程实践要点

1. 设备热插拔检测

public static class UsbHotplug {
   
    private static UsbDeviceList _devices = new();

    public static void MonitorChanges(Action<UsbDevice> added, Action<UsbDevice> removed) {
   
        _devices = UsbDevice.AllDevices;
        Timer timer = new Timer(_ => {
   
            var current = UsbDevice.AllDevices;
            var addedDevices = current.Except(_devices).ToList();
            var removedDevices = _devices.Except(current).ToList();

            addedDevices.ForEach(added);
            removedDevices.ForEach(removed);

            _devices = current;
        }, null, 1000, 1000);
    }
}

2. 数据校验机制

// CRC16校验
public ushort CalculateCRC(byte[] data) {
   
    ushort crc = 0xFFFF;
    foreach (byte b in data) {
   
        crc ^= (ushort)(b << 8);
        for (int i = 0; i < 8; i++) {
   
            crc <<= 1;
            if ((crc & 0x10000) != 0) crc ^= 0x1021;
        }
    }
    return crc;
}

// 数据封装
public byte[] CreatePacket(byte[] payload) {
   
    ushort crc = CalculateCRC(payload);
    return new byte[] {
    0xAA, 0x55 } 
        .Concat(payload)
        .Concat(BitConverter.GetBytes(crc))
        .ToArray();
}

五、调试与优化

1. 调试工具推荐

  • USBView:查看设备拓扑和端点信息
  • Wireshark+USBPcap:抓取USB通信数据包
  • Bus Hound:实时监控USB数据流量

2. 性能优化方案

// 双缓冲区技术
private byte[] _bufferA = new byte;
private byte[] _bufferB = new byte;
private bool _useBufferA = true;

// 零拷贝传输
public async Task<int> HighSpeedTransfer(byte[] data) {
   
    var buffer = _useBufferA ? _bufferA : _bufferB;
    Array.Copy(data, buffer, data.Length);
    _useBufferA = !_useBufferA;

    return await _writer.WriteAsync(buffer, 100);
}

参考代码 C# USB 发送和接收数据 www.youwenfan.com/contentalg/92801.html

六、完整项目结构

USBCommunication/
├── Libs/                # 第三方库
│   └── LibUsbDotNet.dll
├── Devices/             # 设备配置
│   └── DeviceConfig.json
├── Src/
│   ├── UsbService.cs    # 核心通信类
│   ├── ProtocolHandler.cs # 协议解析
│   └── HotplugMonitor.cs
└── Tests/               # 单元测试
    └── UsbCommunicationTests.cs

七、常见问题解决方案

  1. 访问被拒绝 以管理员身份运行程序 使用Zadig工具安装WinUSB驱动
  2. 数据丢失 增加数据包序号校验 设置合理的超时时间(建议500-2000ms)
  3. 设备识别失败 检查VID/PID是否正确 使用lsusb(Linux)或USBDeview(Windows)验证设备状态

该方案支持HID设备、CDC类设备等多种USB通信场景,可通过扩展以下功能增强系统:

  • 多设备并发:使用ConcurrentDictionary管理多个连接
  • 固件升级:实现DFU协议支持
  • 加密传输:集成AES-256加密算法
相关文章
C#学习相关系列之多线程---ConfigureAwait的用法
C#学习相关系列之多线程---ConfigureAwait的用法
603 0
|
XML 存储 数据可视化
Flowable学习笔记(一、入门)
Flowable学习笔记(一、入门)
3166 1
Flowable学习笔记(一、入门)
|
4月前
|
开发工具 git
Git版本控制工具合并分支merge命令操作流程
通过以上步聚焦于技术性和操作层面指南(guidance), 可以有效管理项目版本控制(version control), 并促进团队协作(collaboration).
916 15
|
11月前
|
前端开发 测试技术 API
我同学不知道UnoCSS是什么,我教他用之后效率直接倍增
原子化 CSS 是一种 CSS 的架构方式,它倾向于小巧且用途单一的 class,并且会以视觉效果进行命名。可以将原子化的 CSS 框架理解为这类 CSS 的统称
1486 5
|
缓存 运维 Java
解决Spring Boot中的内存泄漏问题
解决Spring Boot中的内存泄漏问题
|
缓存 Java 编译器
JRE、JDK、JVM 和 JIT 之间的区别详解
【8月更文挑战第22天】
815 0
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
896 0
|
C# UED 开发者
WPF打印功能实现秘籍:从页面到纸张,带你玩转WPF打印技术大揭秘!
【8月更文挑战第31天】在WPF应用开发中,打印功能至关重要,不仅能提升用户体验,还增强了应用的实用性。本文介绍WPF打印的基础概念与实现方法,涵盖页面元素打印、打印机设置及打印预览。通过具体案例,展示了如何利用`PrintDialog`和`PrintDocument`控件添加打印支持,并使用`PrinterSettings`类进行配置,最后通过`PrintPreviewWindow`实现打印预览功能。
1258 0
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
1442 0

热门文章

最新文章