前言
我有一个朋友,是个前端切图崽。他第一次接到USB通信的需求,自信满满对着产品说:“不就是一根USB线进行读和写吗?1周就OK!”。我嘲笑道哪有那么简单,但他不屑一顾,我拗不过他。很快地他发现不对,十分有九分的不对劲:
- 串口通信为什么要配置那么多玩意?什么是波特率?数据位?停止位?校验位?
- HID 设备又是什么新玩意?和USB 设备有什么区别?
Web Serial API、WebHID API和WebUSB API这三个应该怎么选择?
版本已经排期,他灰灰地找到我寻求帮助,不然交付Delay 就是木已成舟的事情。刚好我也没接触过这块的知识,那就一起学习一下,开启这趟前端开发者的USB通信之旅~~~
串口
串口,原名叫做串行接口(Serial Interface)别名叫COM口(串行通讯端口( cluster communication port ))。串行通信常用的逻辑电路是UART(异步串行 Universal Asynchronous Receiver/Transmitter)。 作为刚接触的开发简单记住一点就行:只要进行串行通讯的端口都属于串口。
我还以为因为那设备的线束是一串串的才叫串口呢
串口用于串列式逐位元数据传输,传统串口有如RS-232、RS-485。特点是:
- 距离短、速率低
- 结构简单、支持热插拔
当然,有串行就会有并行,这里就不额外拓展介绍并口(打印机端口)。
USB
USB(Universal Serial Bus,通用串行总线)是串口的一种,是一种广泛使用的接口标准,也是一种输入输出接口的技术规范(USB 3.x)。
从键盘、鼠标到打印机、存储设备,USB接口几乎无处不在。对比传统串口,特点是:
- 高速传输:常见的
USB 3.x可最高支持5 ~10 Gbps速率 - 广泛支持:统一的接口标准,被大部分的操作系统和软件所支持
- 无需额外电源:USB端口可以为设备提供电源,简化了外部电源的需求
HID
HID(Human Interface devices,人机接口设备)是USB设备的一种(蓝牙连接也常见),一般是直接与人交互的设备,例如键盘(Keyboard)、鼠标(mouse)、游戏手柄(joysticks)等。
需要注意的是:一般情况下,一个USB设备可能会对应多个HlD接口(如下图),用来实现一些骚操作,如“模拟多个键盘的实现全键无冲方案”
HID设备并不一定要有人机交互功能,只要遵循HID协议的设备都是HID设备。对比于其他USB设备,特点是:
- 低延迟:HID设备通常要求较低的响应时间,适合实时交互,如键盘和鼠标输入。
- 无需专用驱动:操作系统通常内置了通用HID驱动,用户无需额外安装驱动,即可使用。
- 兼容性:遵循统一的HID协议,使其具有良好的跨平台兼容性,可以在多种操作系统和硬件平台上使用。
Web的三种USB通信API
学习完一些基础概念,我们来看看,现代浏览器提供的一些API,让我们前端可以直接与USB设备进行交互。
Web Serial API:串口通信的桥梁
适用设备
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:与人机交互设备对话
适用设备
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 API | WebHID API | WebUSB 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设备如键盘、鼠标需要快速响应,较小的数据包能减少传输延迟。
-
资源优化
较小的数据包占用较少的内存和带宽,适合资源有限的嵌入式系统。
-
标准化
64字节的限制简化了设备与主机之间的通信,降低了实现复杂性。
-
功耗考虑
较小的数据包有助于降低功耗,延长电池寿命,适合无线HID设备。
结语
这趟简短的前端开发者的USB通信之旅希望能帮到你。