【STM32】USB HID Keyboard

前言

接續上一篇【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 鍵盤掃描碼表格

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);
	  }
  }