前言
接續上一篇【STM32】USB HID Mouse,再來要把HID descripotr改為keyboard
1. USB HID Descriptor Tool
從HID Descriptor Tool開啟keybrd.hid
keybrd.hid長度63 bytes,傳輸封包8 bytes
Keyboard HID Package
| Byte | Content | Descriptor |
|---|---|---|
| 1 | Modifier keys (1 byte) | 修饰符键的状态:Ctrl、Shift、Alt、GUI等 |
| 2 | Reserved (1 byte) | 保留字节,通常为 0 |
| 3-8 | Key codes (6 bytes) | 6 个按键代码,表示当前按下的键的扫描码 |
Modifier keys
- Bit 6:Right Alt
- Bit 5:Right Shift
- Bit 4:Right Ctrl
- Bit 3:Left GUI
- Bit 2:Left Alt
- Bit 1:Left Shift
- Bit 0:Left Ctrl
HID 鍵盤掃描碼表格 Scan Key codes
以下是 HID 鍵盤掃描碼與鍵位之間的對應表。
| 按鍵名稱 | 掃描碼 (Key Code) |
|---|---|
| A | 0x04 |
| B | 0x05 |
| C | 0x06 |
| D | 0x07 |
| E | 0x08 |
| F | 0x09 |
| G | 0x0A |
| H | 0x0B |
| I | 0x0C |
| J | 0x0D |
| K | 0x0E |
| L | 0x0F |
| M | 0x10 |
| N | 0x11 |
| O | 0x12 |
| P | 0x13 |
| Q | 0x14 |
| R | 0x15 |
| S | 0x16 |
| T | 0x17 |
| U | 0x18 |
| V | 0x19 |
| W | 0x1A |
| X | 0x1B |
| Y | 0x1C |
| Z | 0x1D |
| 1 | 0x1E |
| 2 | 0x1F |
| 3 | 0x20 |
| 4 | 0x21 |
| 5 | 0x22 |
| 6 | 0x23 |
| 7 | 0x24 |
| 8 | 0x25 |
| 9 | 0x26 |
| 0 | 0x27 |
| Enter | 0x28 |
| Spacebar | 0x2C |
| Backspace | 0x2A |
| Tab | 0x2B |
| Escape | 0x29 |
| F1 | 0x3A |
| F2 | 0x3B |
| F3 | 0x3C |
| F4 | 0x3D |
| F5 | 0x3E |
| F6 | 0x3F |
| F7 | 0x40 |
| F8 | 0x41 |
| F9 | 0x42 |
| F10 | 0x43 |
| F11 | 0x44 |
| F12 | 0x45 |
或者可以查閱USB HID Usage Tables的 Table 12: Keyboard/Keypad Page
2. STM32CubeIDE
把keybrd.hid複制覆蓋usbd_hid.c的 HID_MOUSE_ReportDesc[]
usbd_hid.c
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x05, 0x08, // USAGE_PAGE (LEDs)
0x19, 0x01, // USAGE_MINIMUM (Num Lock)
0x29, 0x05, // USAGE_MAXIMUM (Kana)
0x91, 0x02, // OUTPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0 // END_COLLECTION
usbd_hid.h
HID report長度改為63
#define HID_MOUSE_REPORT_DESC_SIZE 63U
usbd_hid.c
USBD_HID_CfgFSDesc[]的 nInterfaceProtocol 改為 1:keyboard
main.c
應用程式在按下User button(PA0)時輸入 Shift+'a'
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == 1)
{
extern USBD_HandleTypeDef hUsbDeviceFS;
int8_t data[8] = {0,0,0,0,0,0,0,0};
//Key 'a'
data[0] = 0x02;//shift
data[2] = 0x04;//'a'
USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&data, 8);
HAL_Delay(15);
memset(data, 0, 9);
USBD_HID_SendReport(&hUsbDeviceFS,(uint8_t*)&data, 8);
HAL_Delay(300);
}
}



留言
張貼留言