开始前适用开发板:ESP32-P4 + ESP32-C5 · 开发框架:ESP-IDF
适用开发板:P4C5 · 工程
02.beginner.usb_hid_keyboard· targetesp32p4
连接:Type-C 接 PC(Device 模式),板子被识别为 USB 键盘
学习时长:约 20 分钟 · 难度:★★☆☆☆
学习目标
完成本节后,你将能够:
- 理解 USB HID 设备的枚举与识别过程
- 掌握 CherryUSB 协议栈的基本使用
- 了解 HID Report Descriptor 的结构与含义
- 在 MIPI 大屏上观察 USB 设备状态变化
1. 这个例子在干嘛
把 ESP32-P4 变成一个 USB 键盘——连接到电脑后自动发送按键 a,你会在电脑的记事本中看到字符出现。P4C5 版比 Korvo 多了一个优势:MIPI 大屏实时显示 USB 状态。
┌──────────────┐ USB Type-C ┌──────────┐
│ ESP32-P4 │◄────────────────►│ PC │
│ HID Keyboard │ │ (Host) │
│ │ ─────────► │ │
│ MIPI 屏状态 │ 键盘报告 │ 记事本 │
└──────────────┘ └──────────┘
2. 使用前注意事项
- 使用 数据线(不是纯充电线)连接 P4C5 USB 口与 PC
- 烧录前:把光标从重要文本框移开!设备上电会立即"打字"
- 设备管理器 → 键盘 → 会出现 HID Keyboard Device(名含 CherryUSB HID DEMO)
- 如需重新烧录但设备一直在打字:断电 → BOOT 键 → 上电进下载模式
3. 编译烧录
cd P4_C5_4.3_Firmware\02.beginner.usb_hid_keyboard
idf.py set-target esp32p4
idf.py build flash monitor
4. 运行现象
| 阶段 | MIPI 屏幕显示 | PC 端 | 串口 |
|---|---|---|---|
| 上电 | USB device init | — | USB 初始化日志 |
| 枚举完成 | USB configured | 设备管理器出现 HID | Enumeration done |
| 发送按键 | sending key demo | 记事本出现 a | Send key report |
| 空闲 | 状态保持 | 无更多输入 | — |
5. USB HID 协议详解
5.1 什么是 USB HID?
HID(Human Interface Device)是 USB 标准中最常见的设备类之一。键盘、鼠标、手柄、触摸板都属于 HID 设备。最大特点:免驱动,所有操作系统内置 HID 驱动。
5.2 USB 枚举过程(简化版)
1. 设备插入 → Host 检测到电压变化
2. Host 发送 GET_DESCRIPTOR → 设备返回设备描述符
3. Host 分配地址 → SET_ADDRESS
4. Host 请求配置描述符 → 设备返回 HID 报告描述符
5. Host 读取 Report Descriptor → "哦,这是一个键盘!"
6. Host 安装 HID 驱动 → 枚举完成
7. 设备开始通过中断 IN 端点发送键盘报告
5.3 Report Descriptor
Report Descriptor 是 HID 设备的"身份证",告诉 Host 这个设备会发什么数据:
hid_keyboard_report_desc (63 字节):
├── Usage Page: Generic Desktop
├── Usage: Keyboard
├── Collection: Application
│ ├── 输入:修饰键(8 位 bitmap)
│ ├── 保留:1 字节常量
│ ├── 输出:LED 指示灯(Caps Lock 等)
│ └── 输入:键码数组(6 个键位)
└── End Collection
5.4 键盘报告格式(8 字节)
字节: [0] [1] [2] [3] [4] [5] [6] [7]
含义: 修饰键 保留 键1 键2 键3 键4 键5 键6
修饰键 (bitmap):
bit 0 = Left Ctrl bit 4 = Right Ctrl
bit 1 = Left Shift bit 5 = Right Shift
bit 2 = Left Alt bit 6 = Right Alt
bit 3 = Left GUI bit 7 = Right GUI
示例:
[0x00, 0x00, 0x04, 0,0,0,0,0] → 按下 'a'
[0x02, 0x00, 0x04, 0,0,0,0,0] → 按下 'A' (Shift+a)
[0x01, 0x00, 0x06, 0,0,0,0,0] → Ctrl+C
[0x00, 0x00, 0x00, 0,0,0,0,0] → 全部松开
关键:每次按键后 必须发送全零报告 表示松开,否则电脑认为键一直按着。
6. 关键文件与代码解析
| 文件 | 作用 | 重点关注 |
|---|---|---|
main/app_main.c | 屏幕显示 + USB 初始化 + 测试调用 | hid_keyboard_init1() |
main/usbx_demo.c | Report Descriptor + 报告发送 | hid_keyboard_test() |
main/usb_config.h | CherryUSB 配置参数 | 端点、缓冲大小 |
CherryUSB 使用流程
app_main()
├── MIPI 屏初始化(BSP)
├── CherryUSB Device 初始化
│ ├── 注册设备描述符
│ ├── 注册配置描述符(包含 HID 接口)
│ └── 注册 Report Descriptor
├── USB Device 启动
├── 等待枚举完成
└── hid_keyboard_test()
├── 填充 8 字节报告(键码 0x04 = 'a')
├── 通过中断 IN 端点发送
├── 延时
└── 发送全零报告(松开)
发送状态管理
hid_state: IDLE → BUSY → IDLE
- IDLE:可以发送新报告
- BUSY:上一次发送尚未完成(中断 IN 传输中)
- 必须等 IDLE 才能发送下一个报告,否则数据丢失
7. 与 HID 鼠标的区别
| 对比项 | HID 键盘 | HID 鼠标 |
|---|---|---|
| 报告长度 | 8 字节 | 通常 4 字节 |
| 报告内容 | [修饰键, 保留, 键1~6] | [按钮, X位移, Y位移, 滚轮] |
| 描述符 | Usage: Keyboard | Usage: Mouse → Pointer |
| 数据类型 | 绝对值(键码) | 相对值(位移量) |
见 02.beginner.usb_hid_mouse 对比学习。
8. 常见问题与排查
| 现象 | 可能原因 | 解决方案 |
|---|---|---|
| PC 无设备出现 | 线材不支持数据传输 | 换数据线 |
| PC 无设备出现 | USB 模式配置错误 | 确认 Device 模式(非 Host) |
| 有设备无按键 | hid_keyboard_test 未被调用 | 检查 app_main 流程 |
| 有设备无按键 | 端点 BUSY | 等待上次传输完成 |
| 记事本出现乱码 | 键码或修饰键字节错误 | 核对 HID Usage Table |
| 不停重复打字 | 代码在循环中反复发送 | 改为发送一次后 break |
| 烧录困难 | 设备一直在打字 | 断电 → BOOT → 上电 |
9. 动手改造建议
- 修改按键:将
HID_KBD_USAGE_A(0x04)改为空格(0x2C)或回车(0x28) - 自动打字机:循环发送 "Hello P4C5\n"
- 快捷键:发送
Ctrl+C/Ctrl+V(修改修饰键字节) - 触摸屏键盘:在 MIPI 大屏上画虚拟键盘,触摸按钮映射到 HID 报告
- 复合设备:同时注册键盘 + 鼠标,实现一根线两个设备
- 扩展学习:跑
04.advanced.usb_extended_display看更复杂的 USB 应用
10. 常用键码速查
| 键码 (hex) | 按键 | 键码 (hex) | 按键 |
|---|---|---|---|
| 0x04~0x1D | a~z | 0x1E~0x27 | 1~0 |
| 0x28 | Enter | 0x29 | Escape |
| 0x2A | Backspace | 0x2B | Tab |
| 0x2C | Space | 0x4F | Right Arrow |
| 0x50 | Left Arrow | 0x51 | Down Arrow |
| 0x52 | Up Arrow | — | — |
11. 知识延伸
- CherryUSB:国产开源 USB 协议栈,支持 Device + Host 双模式,ESP32-P4 和 ESP32-S3 均可使用
- USB 2.0 速度:Full Speed(12 Mbps)/ High Speed(480 Mbps),P4 支持 High Speed
- 中断 IN 端点:HID 设备专用传输方式,保证延迟(轮询间隔通常 1~10 ms)
- 复合设备:一个 USB 口注册多个 Interface,可同时做键盘+鼠标+存储
12. 下一步
| 方向 | 推荐例程 | 说明 |
|---|---|---|
| HID 鼠标 | 02.beginner.usb_hid_mouse | 报告格式对比 |
| USB 扩展屏 | 04.advanced.usb_extended_display | 复杂 USB 应用 |
| 通用 USB 教程 | USB 教程 | 深入原理 |
| Wi-Fi 联网 | wifi_station | 网络方向 |
酷世DIY · Kevincoooool