首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C# USB 設備通信實戰:WinUSB / libusb / DeviceIoControl 三大方案選型指南

     編輯:程式設計綜合問答

場景釐清

已知:設備路徑、句柄 (`CreateFile` 成功)、通信協議格式 (經 Bus Hound 抓取)。
目標:發送指令控制設備 (價值 200 萬儀器)。

方案對比

方案適用條件C# 實現難度穩定性/維護性
WinUSB (Microsoft 官方)設備使用 WinUSB.sys 驅動 (INF 指定)中 (需 P/Invoke `WinUSB.dll`)高、原生支援、無需第三方
libusbK / libusb-win32設備使用 libusb 驅動 (通用、跨平台)中 (C# 封裝 `LibUsbDotNet`)高、成熟庫、支援異步
HID Class (人體介面裝置)設備枚舉為 HID (Usage Page 0xFF00 等)低 (`HidLibrary` NuGet)最高、無需驅動開發、系統原生
虛擬串口 (CDC ACM)設備枚舉為 COM 口極低 (`SerialPort` 類)高、通用、但延遲較大
自定義驅動 + DeviceIoControl特殊需求、高性能、內核模式極高 (需 C/C++ 寫驅動 + 簽名)最高控制力、但開發成本巨大

關鍵判斷:設備當前使用何種驅動?


// 1. 設備管理器 → 查看設備屬性 → 驅動程序詳情
// WinUSB: winusb.sys
// libusb: libusb0.sys / libusbK.sys
// HID: hidusb.sys + hidclass.sys
// CDC: usbser.sys

方案一:HID 設備 (最推薦嘗試)

許多儀器為兼容性枚舉為 HID。使用 `HidLibrary` (NuGet):


using HidLibrary;

var devices = HidDevices.Enumerate(vid: 0x1234, pid: 0x5678); // 替換實際 VID/PID
if (devices.Any()) {
    var device = devices.First();
    device.OpenDevice();
    
    // 發送指令 (Report ID + 數據)
    byte[] report = new byte[64];
    report[0] = 0x00; // Report ID (若無則 0)
    report[1] = 0x01; // 指令碼
    // ... 填充協議數據 ...
    device.WriteReport(report);
    
    // 讀取回應
    var readReport = device.ReadReport(1000); // 1秒超時
    if (readReport != null) {
        byte[] data = readReport.Data;
        // 解析協議
    }
    device.CloseDevice();
}

方案二:WinUSB (通用 USB 介面)

需 P/Invoke `WinUSB.dll`,定義結構體 `WINUSB_INTERFACE_HANDLE`、`WINUSB_PIPE_INFORMATION` 等。
**推薦使用成熟封裝**:`Usb.Net` (NuGet) 或參考 Microsoft 官方範例 `WinUSB_CSharp`。

方案三:libusb (跨平台首選)


// LibUsbDotNet NuGet
using LibUsbDotNet;
using LibUsbDotNet.Main;

UsbDeviceFinder finder = new UsbDeviceFinder(0x1234, 0x5678);
UsbDevice device = UsbDevice.OpenUsbDevice(finder);
if (device != null) {
    // 宣告介面
    device.ClaimInterface(0);
    
    // 批量傳輸端點 (OUT 發送, IN 接收)
    UsbEndpointWriter writer = device.OpenEndpointWriter(WriteEndpointID.Ep01);
    UsbEndpointReader reader = device.OpenEndpointReader(ReadEndpointID.Ep01);
    
    // 發送
    int bytesWritten;
    writer.Write(commandBuffer, 1000, out bytesWritten); // 1秒超時
    
    // 接收
    int bytesRead;
    ErrorCode ec = reader.Read(responseBuffer, 1000, out bytesRead);
    
    device.ReleaseInterface(0);
    device.Close();
}

協議實現核心建議

  1. 封裝協議層:建立 `DeviceProtocol` 類,方法 `SendCommand(cmd, params)` 返回 `Response` 物件,隱藏底層報文組裝/校驗 (CRC/Checksum)。
  2. 異步非阻塞:UI 執行緒勿直接 `Read`,使用 `Task.Run` + `async/await` 或 `BackgroundWorker`。
  3. 重試與超時:指令發送失敗自動重試 3 次,總超時 5 秒。
  4. 日誌記錄:所有原始報文 (十六進位) 寫入滾動日誌,便於廠商排查。
  5. 安全鎖:關鍵操作 (校準、擦除) 需雙重確認對話框 + 密碼/硬體鑰匙。

廠商支援關鍵

**務必向廠商 (Thermo Fisher) 索取**:

  • 官方 SDK / DLL / .NET 組件 (最佳)。
  • 完整通信協議文檔 (命令碼、參數格式、返回碼、錯誤碼)。
  • 驅動程序安裝包 (含 INF、CAT 簽名文件)。
  • 示例代碼 (C++/C#/Python/LabVIEW)。

無文檔逆向協議風險極高,可能導致設備損壞或數據錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved