DWG · IDANT-JRN-002 · BLE JOURNAL
BLE JRN-002 · 18 分钟

BLE HID 低延迟:工程取舍

从蓝牙规范到主机栈,把延迟从 30ms 砍到 8ms 的全过程

这篇笔记针对一个具体目标 —— **BLE 游戏手柄端到端 < 10ms**。 这个目标在 5 年前几乎不可能(蓝牙规范本身就限制),现在是工程极限。

下面 7 个段落覆盖:
连接参数、PHY、通知机制、主机栈差异、测试方法学。
全是踩过坑沉淀下来的,不是教科书。

SPEC · IMPL · TEST
01
SECTION

为什么 < 10ms 是底线

竞技手游对操控延迟的容忍阈值大约在 16ms(一帧)以内 —— 超过会被职业玩家直接察觉。这 16ms 要从手指按下分到三段:① 按键到 MCU(< 1ms 硬件去抖)② MCU 到主机(这是 BLE HID 部分)③ 主机渲染(5-8ms)。

留给蓝牙的预算只有 **8-10ms**。听起来宽裕,但蓝牙规范的物理极限就在这附近 —— 没有任何"轻松达到"的捷径。

02
SECTION

Connection Interval 的"黄金 7.5ms"

BLE 4.x 规范的 Connection Interval 范围是 **7.5ms 到 4s**。HID 设备一直被允许使用最低值 7.5ms 这个"特权"(其他 GATT 应用通常被推荐 ≥ 30ms)。

但 iOS / macOS 实际只接受 **15ms 起步**(除非提交 MFi 认证或开启了 Game Controller Framework 路径)。Android 上 7.5ms 真的可以谈下来 —— 但要在连接建立后立刻 Connection Parameter Update Request,否则系统按默认 30ms 走。

经验值:**手柄出厂初始化时立刻请求 7.5ms,主机会同意 95%+**。

03
SECTION

Slave Latency 必须是 0

Slave Latency 允许从机跳过 N 个连接事件不响应 —— 用于省电(鼠标键盘空闲时跳过几次响应睡眠)。

但 HID 游戏外设的本质是 **任何时刻都可能有按键**。Slave Latency = 0 是硬约束。如果你看到平均延迟 22ms 而 Connection Interval 设的 7.5ms ——99% 是 Slave Latency 偷偷加了几个事件。

平台兼容性:iOS 不允许 Slave Latency > 30,Android 允许更大但 HID 场景应永远为 0。

04
SECTION

PHY 选择:1M、2M、还是 Coded?

BLE 5.0 引入 2M PHY,理论上把数据包传输时间砍半 —— 这不直接降低延迟(Connection Interval 决定的是事件间隔),但**减少 Air Time** 后:

① 同样的 Connection Interval 内,可以塞更多消息(多帧合一 / 连续上报) ② 抗干扰更好(更短的暴露窗口) ③ 与 Wi-Fi 共存时碰撞概率更低

但 2M PHY 在嘈杂环境(机场 / 网吧 / 电竞馆)的连接稳定性反而下降。**PHY 优先级建议:默认 1M / Auto,用户在"低延迟模式"下手动切 2M。**

Coded PHY(S=2 / S=8)适合长距离低速 —— 完全不适合 HID。

05
SECTION

Notify 队列:HID 唯一选项

GATT 通知机制有三种:Read / Notify / Indicate。HID 用 **Notify** 是唯一合理选择: - Read 是主机轮询,延迟取决于轮询频率,不可控 - Indicate 需要 ACK,每次往返多 7.5ms,HID 无法接受 - Notify 是从机推、不需 ACK —— 适合"高频低重要性"消息

Notify 的代价:可能丢包(无 ACK)。HID 协议设计时已考虑:每帧消息包含完整状态(不是增量),偶发丢包不影响后续状态。**手柄不能用增量消息,全状态推送才是对的。**

06
SECTION

主机栈差异:你以为兼容 = 实际兼容

蓝牙规范是规范,主机实现是另一回事。同一个固件在五个平台上的实测延迟(按 7.5ms Connection Interval / Slave Latency 0 / 1M PHY):

- **Android 13+**:约 9-12ms(最优) - **iOS 17+ / Game Controller Framework**:约 13-16ms(强制 15ms 间隔) - **Windows 11 + 原生栈**:约 15-22ms(栈实现波动大) - **Windows 11 + Razer / Logitech 接收器**:约 7-10ms(专有 2.4G 协议绕开 BLE) - **macOS Sonoma**:约 18-25ms

竞技手游用户多在 Android 和 iOS —— 这两个是优化主战场。Windows 桌面游戏建议出厂带 2.4G dongle 走专有协议。

07
SECTION

测试方法:示波器是唯一标准

不要相信平均延迟、最大延迟这些聚合数字 —— P99 和 jitter 才决定用户体验。 正确测试设备:

① **Logic Analyzer** 抓按键 GPIO + 主机渲染时间戳(需要主机端有时间戳输出,例如 Android 端 evdev 注入) ② **示波器双通道**:通道 1 接键盘按键的 MCU input pin,通道 2 接 USB capture 设备解调出的 HID 报告

测一晚(10K+ 事件),看 P50 / P95 / P99 / Max 四个数字。**单纯报"平均 12ms"的产品广告,多半 P99 在 50ms+**。

SUMMARY · 总结
Cheat Sheet

7 项工程取舍小抄

  1. 01·Connection Interval:Android 7.5ms / iOS 15ms(系统强制)
  2. 02·Slave Latency:游戏 HID 永远为 0
  3. 03·PHY:默认 1M,用户可选 2M(安静环境收益最大)
  4. 04·消息机制:Notify,全状态推送,不发增量
  5. 05·多平台:Windows 桌面建议带 2.4G dongle 兜底
  6. 06·测试:示波器 + Logic Analyzer,看 P99,不看平均
  7. 07·当延迟 > 15ms:先查 Slave Latency,9/10 是它

BLE HID 的工程乐趣在于 —— **每节省 1ms 都是真实的体验提升**。
不是工程师自嗨,是用户能直接感受的"跟手感"。

青莲 · idant