从零到入门:前端开发者的USB通信之旅

871 阅读7分钟

前言

我有一个朋友,是个前端切图崽。他第一次接到USB通信的需求,自信满满对着产品说:“不就是一根USB线进行读和写吗?1周就OK!”。我嘲笑道哪有那么简单,但他不屑一顾,我拗不过他。很快地他发现不对,十分有九分的不对劲:

  • 串口通信为什么要配置那么多玩意?什么是波特率?数据位?停止位?校验位?
  • HID 设备又是什么新玩意?和USB 设备有什么区别?
  • Web Serial APIWebHID APIWebUSB API 这三个应该怎么选择?

版本已经排期,他灰灰地找到我寻求帮助,不然交付Delay 就是木已成舟的事情。刚好我也没接触过这块的知识,那就一起学习一下,开启这趟前端开发者的USB通信之旅~~~

串口

串口,原名叫做串行接口(Serial Interface)别名叫COM口(串行通讯端口( cluster communication port ))。串行通信常用的逻辑电路是UART(异步串行 Universal Asynchronous Receiver/Transmitter)。 作为刚接触的开发简单记住一点就行:只要进行串行通讯的端口都属于串口

我还以为因为那设备的线束是一串串的才叫串口呢

串口用于串列式逐位元数据传输,传统串口有如RS-232、RS-485。特点是:

  • 距离短、速率低
  • 结构简单、支持热插拔

当然,有串行就会有并行,这里就不额外拓展介绍并口(打印机端口)。

主板接口.png

USB

USB(Universal Serial Bus,通用串行总线)是串口的一种,是一种广泛使用的接口标准,也是一种输入输出接口的技术规范(USB 3.x)。

从键盘、鼠标到打印机、存储设备,USB接口几乎无处不在。对比传统串口,特点是:

  • 高速传输:常见的USB 3.x可最高支持5 ~10 Gbps速率
  • 广泛支持:统一的接口标准,被大部分的操作系统和软件所支持
  • 无需额外电源:USB端口可以为设备提供电源,简化了外部电源的需求

usb.webp

HID

HID(Human Interface devices,人机接口设备)是USB设备的一种(蓝牙连接也常见),一般是直接与人交互的设备,例如键盘(Keyboard)、鼠标(mouse)、游戏手柄(joysticks)等。

需要注意的是:一般情况下,一个USB设备可能会对应多个HlD接口(如下图),用来实现一些骚操作,如“模拟多个键盘的实现全键无冲方案”

image-20250123173948169.png

HID设备并不一定要有人机交互功能,只要遵循HID协议的设备都是HID设备。对比于其他USB设备,特点是:

  • 低延迟:HID设备通常要求较低的响应时间,适合实时交互,如键盘和鼠标输入。
  • 无需专用驱动:操作系统通常内置了通用HID驱动,用户无需额外安装驱动,即可使用。
  • 兼容性:遵循统一的HID协议,使其具有良好的跨平台兼容性,可以在多种操作系统和硬件平台上使用。

Web的三种USB通信API

学习完一些基础概念,我们来看看,现代浏览器提供的一些API,让我们前端可以直接与USB设备进行交互。

Web Serial API:串口通信的桥梁

Web Serial Debug-浏览器串口调试工具

适用设备

Web Serial API主要用于与串口设备通信。这些设备通常通过RS-232、RS-485或USB虚拟串口连接。例如,工业传感器、嵌入式系统、Arduino开发板等都属于串口设备。

特点
  • 通信协议:开发者需要自行定义通信协议,因为串口设备通常不遵循统一的标准。
  • 数据传输:支持文本和二进制数据的传输,但传输速率相对较低。
  • 即插即用:需要手动配置波特率等参数,不支持即插即用。
  • 适用场景:适用于需要与工业设备、传感器或嵌入式系统交互的场景。
示例代码
async function connectSerial() {
    const port = await navigator.serial.requestPort();
    await port.open({ baudRate: 9600 });
​
    const writer = port.writable.getWriter();
    await writer.write(new Uint8Array([0x01, 0x02, 0x03]));
    writer.releaseLock();
​
    const reader = port.readable.getReader();
    const { value, done } = await reader.read();
    console.log("Received:", value);
}

WebHID API:与人机交互设备对话

HID Explorer-浏览器HID调试工具

适用设备

WebHID API主要用于与HID设备(Human Interface Device,人机接口设备)通信。这些设备包括键盘、鼠标、游戏手柄、触摸屏等。它们通常通过USB接口连接,但也可以通过蓝牙连接。

特点
  • 通信协议:遵循HID协议,设备的通信方式是标准化的。
  • 数据传输:基于HID报告(如输入报告、输出报告),数据传输通常是低延迟的。
  • 即插即用:支持即插即用,无需额外驱动。
  • 适用场景:适用于需要与人机交互设备(如键盘、鼠标)进行通信的场景。
示例代码
async function connectHID() {
    const devices = await navigator.hid.requestDevice({ filters: [{ vendorId: 0x1234 }] });
    const device = devices[0];
    await device.open();
​
    await device.sendReport(0x01, new Uint8Array([0x01, 0x02, 0x03]));
​
    device.addEventListener('inputreport', event => {
        console.log("Received:", new Uint8Array(event.data.buffer));
    });
}

WebUSB API:高性能的USB通信

适用设备

WebUSB API用于与自定义USB设备通信。这些设备可能包括打印机、摄像头、存储设备等。它们通常使用自定义协议,而不是标准的HID协议。

特点
  • 通信协议:绕过操作系统驱动,直接与设备通信,支持自定义USB协议。
  • 数据传输:支持批量传输,适合大数据量的高速传输。
  • 即插即用:需要手动配置,不支持即插即用。
  • 适用场景:适用于需要高性能通信或直接访问USB协议的场景。
示例代码
async function connectUSB() {
    const device = await navigator.usb.requestDevice({ filters: [{ vendorId: 0x1234 }] });
    await device.open();
    await device.selectConfiguration(1);
    await device.claimInterface(0);
​
    await device.transferOut(1, new Uint8Array([0x01, 0x02, 0x03]));
​
    const result = await device.transferIn(2, 64);
    console.log("Received:", new Uint8Array(result.data.buffer));
}

总结:选择合适的API

特性Web Serial APIWebHID APIWebUSB API
适用设备串口设备(RS-232、RS-485等)HID设备(键盘、鼠标等)USB设备(自定义设备、打印机等)
通信协议自定义协议HID协议USB协议
数据传输类型文本或二进制HID报告(二进制)二进制
通信速率低速率低到中速率高速率
即插即用需要配置波特率等参数支持需要手动配置
适用场景工业设备、传感器、嵌入式系统人机交互设备自定义USB设备、高性能通信

Q&A

串口通信为什么要配置那么多玩意?

串口通信是一种异步通信方式,发送方和接收方之间需要相同的时钟信号,才来确保双方能够正确地同步和解析数据。而以下参数的配置对于确保数据传输的准确性和可靠性至关重要。

  • 波特率(Baud Rate)

    波特率它表示每秒传输的符号数(bit),确保了发送方和接收方的时钟同步,使它们能够正确地识别数据位。

  • 数据位(Data Bits)

    数据位定义了每个字符的长度(常见的数据位长度有7位和8位),确保发送方和接收方对字符长度有一致的理解。

  • 停止位(Stop Bits)

    停止位是在每个字符传输结束后添加的一段高电平或低电平时间,用于标识一个字符的结束,确保接收方能够正确地检测到字符的结束。

  • 校验位(Parity)

    校验位(常见的校验是奇/偶校验)是一种用于错误检测的机制,它在每个字符中添加一个额外的位,用于检测传输过程中的错误。

一个HID数据包为什么限制64字节?

USB HID协议最初设计时,64字节是一个标准数据包大小。具体有以下几方面的考虑:

  • 低延迟需求

    HID设备如键盘、鼠标需要快速响应,较小的数据包能减少传输延迟。

    轮询hid.png

  • 资源优化

    较小的数据包占用较少的内存和带宽,适合资源有限的嵌入式系统。

  • 标准化

    64字节的限制简化了设备与主机之间的通信,降低了实现复杂性。

  • 功耗考虑

    较小的数据包有助于降低功耗,延长电池寿命,适合无线HID设备。

结语

这趟简短的前端开发者的USB通信之旅希望能帮到你。