# LHR.USBLIN **Repository Path**: lhrbu/LHR.USBLIN ## Basic Information - **Project Name**: LHR.USBLIN - **Description**: LIN USB Driver - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-22 - **Last Updated**: 2026-09-21 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LHR.USBLIN — USB-LIN Box 上位机 SDK USB-LIN Box 的 C# 客户端库。通过 USB Vendor Bulk 端点与 [ESP32-S3 固件](https://gitee.com/lhrbu/lhr_esp32s3_usb_bulk) 通信,把两路 LIN master 能力封装成强类型 API。 - **目标框架**:.NET 10 - **依赖**:LibUsbDotNet 2.x(跨平台,Windows / Linux / macOS) - **协议版本**:proto = 3,配套固件 **1.3.0 及以上** ## 快速开始 ```bash dotnet add package LHR.USBLIN ``` ```csharp using LHR.USBLIN; using var conn = UsbBulkConnection.Open(); // 默认 VID/PID,找不到抛 UsbDeviceNotFoundException var lin = new LINClient(conn); lin.Begin(LINChannel.Ch0, 19200, LINNodeVersion.V2_1); // 下发一帧 lin.MasterRequest(LINChannel.Ch0, 0x3B, LINChecksum.Enhanced, [0x01, 0x02]); // 读从机回帧 var r = lin.SlaveResponse(LINChannel.Ch0, 0x1B, LINChecksum.Enhanced, count: 8); if (r.IsSuccess) Console.WriteLine(BitConverter.ToString(r.Data!)); else if (r.Error.Has(LINBusError.Timeout)) Console.WriteLine("从机无响应"); lin.End(LINChannel.Ch0); ``` **Windows 需先装 WinUSB 驱动**(Zadig 或 `installer/` 里的一键安装器), 否则 `Open()` 会找不到设备 —— 见 [docs/driver-setup.md](docs/driver-setup.md)。 ## 能做什么 | 能力 | API | |------|-----| | 连通性 / 版本 | `Ping()` `Version()` `IsAlive()` | | 通道生命周期 | `Begin(ch, baud, nodeVersion)` `End(ch)` | | master 下发帧 | `MasterRequest(ch, id, crc, data)` / `MasterRequestAll(...)` | | 读 slave 回帧 | `SlaveResponse(ch, id, crc, count)` / `SlaveResponseAll(...)` | | 通道状态 | `Status(ch)` / `StatusAll()` | 两路通道可用 `LINChannel.All` 一次操作,固件侧**真正并行**执行, 墙钟 ≈ 单通道(~10 ms)而非串行两倍。 所有 `*All` 方法返回长度恒为 `LINChannel.Count` 的数组,**下标即通道号**。 ## 两个容易混淆的概念 | 参数 | 属性归属 | 传给谁 | |------|---------|-------| | `LINNodeVersion` | **节点/通道**属性,整条总线单一版本 | `Begin()` | | `LINChecksum` | **帧**属性,同一总线不同 ID 可不同 | 每次 `MasterRequest*` / `SlaveResponse*` | 诊断帧 `0x3C` / `0x3D` 必须用 `LINChecksum.Classic`(LIN 规范硬约束)。 ## 错误处理要点 `LINError` 是一个字节的门面,内部分**两个互斥码段**:LIN 总线错误(`00`–`80`,位掩码可组合) 与协议层错误(`E0`–`FF`,离散取值)。 ```csharp if (r.Error.Has(LINBusError.Timeout)) { /* 总线超时 */ } if (r.Error.Protocol == LINProtocolError.NotInitialized) { /* 通道未 Begin */ } ``` > 位判断**一律用 `Has()`**,不要对 `Error.Raw` 直接做位运算 —— > 两段共用一个字节,`0xE1 & 0x01` 非零会产生"状态机错误"的假阳性。 读类命令(`SlaveResponse*`)不抛 LIN 错误异常,结果放在 `LINChannelResult.Error`; 写类命令抛 `LINCommandException`。断线抛 `UsbDisconnectedException`,可精准捕获触发重连。 ## 仓库结构 ``` src/LHR.USBLIN/ SDK 本体 UsbBulkConnection.cs 传输层:USB Bulk + 行协议 + 设备发现 ILINTransport.cs 行传输抽象(便于离线测试) LIN/LINClient.cs 命令层:拼命令、解析响应 LIN/LINTypes.cs LINChannel / LINError / LINState 等 samples/ 6 个可运行示例,从 Ping 到真实总线验收(LinCheck) tests/ LHR.USBLIN.UnitTests/ 99 个离线单测(无需设备) LHR.USBLIN.Tests/ 硬件压测(需真实设备) drivers/ WinUSB inf + Linux udev 规则 installer/ Windows 驱动一键安装器 canoe/ CANoe LIN 从机联调用 LDF docs/ 详细文档 ``` ## 文档 | 文档 | 内容 | |------|------| | [docs/usage.md](docs/usage.md) | **使用说明** —— 可复制粘贴的完整示例、错误处理、重连样板、FAQ | | `samples/LHR.USBLIN.Sample.LinCheck` | **真实 LIN 总线验收** —— 接好硬件后跑这个,自动分层诊断卡在哪一层 | | [docs/design.md](docs/design.md) | 架构与设计决策、与固件契约的映射 | | [docs/driver-setup.md](docs/driver-setup.md) | 三平台驱动安装 | | [固件协议文档](https://gitee.com/lhrbu/lhr_esp32s3_usb_bulk/blob/master/docs/LinBulkProtocol.md) | 线协议规约(自己拼命令时看) | ## 版本兼容 SDK 与固件的线协议版本必须一致,两者在**独立仓库**、无法原子发布。 **SDK 不做运行期校验** —— 版本配套由使用者自行保证;`Version()` 可读出设备自报的 `proto` 供人工核对。 | SDK | 固件 | proto | |-----|------|-------| | 当前 | 1.3.0+ | 3 | | 旧 | 1.2.x | 2(不兼容) | | 旧 | 1.0–1.1 | 1(不兼容) | ## 构建 ```bash dotnet build LHR.USBLIN.slnx dotnet test tests/LHR.USBLIN.UnitTests # 离线单测,无需设备 ```