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



留言

2024

11-27SPI Flash 操作 (Read/Write/Erase)
11-19Rotary Encoder Switch 旋轉編碼開關
11-14Command Line Interface - CLI via UART
11-14【STM32】USB HID - Volume Control
11-13【STM32】USB Custom HID
11-12【STM32】USB HID Keyboard + Mouse
11-12【STM32】USB HID Keyboard
11-12【STM32】USB HID Mouse
10-15SSD1306 128x64 OLED 【五】Wokwi Animator
09-2432F429IDISCOVERY - - LTDC [3] + FMC (SDRAM) + FatFS
09-2432F429IDISCOVERY - - LTDC [2] + FMC (SDRAM)
09-20STM32 + FatFs + SD card via SPI【三】FatFS指令操作II
09-19STM32 + FatFs + SD card via SPI【二】FatFS指令操作
09-18STM32 + FatFs + SD card via SPI【一】移植FatFS
09-0232F429IDISCOVERY - - LTDC [1]
04-17SSD1306 128x64 OLED 【四】Adafruit / GFX Library
04-17Arduino - Serial Plotter繪圖儀
04-16SSD1306 128x64 OLED 【三】
04-15SSD1306 128x64 OLED 【二】 Datasheet
04-12SSD1306 128x64 OLED 【一】I2C版本
03-20【freeRTOS】vTaskDelay 與 vTaskDelayUntil 的差異
03-19【freeRTOS】API功能列表
03-18【freeRTOS】Day1
03-08MBR和Blank project的差別
03-05刪除註冊檔registry的資料
02-27DFU over Bluetooth Low Energy
02-27nRF Util - 使用手冊
02-26nRF Command Line Tools
02-20建立BootLoader settings
02-19Secure DFU packet (ZIP) build 建立含袐鑰的Zip檔
02-19Secure DFU via BLE
02-19Secure DFU via UART
02-16nRF Util 安裝
01-16nRF52840 ic升級成nRF52840 Dongle的程式

2023

11-21[ SEGGER Embedded Studio ] 新增header files
11-21[ SEGGER Embedded Studio ] 編譯nRF52840時遇到的問題
11-07Arduino Nano ESP32 - Debugging除錯模式
11-03Git快速入手 - 使用Git GUI
10-30Git快速入手 - 使用Git Bash
10-12程式碼高亮顯示 -- google-code-prettify

2022

11-30[EZ-PD] CCG6DF CCG6SF的Host SDK遇到編譯錯誤(一)

2019

05-27[ Eagle PCB ] 合板成品
05-23#CASE_001_USB_TOOL_RL78_G12
05-22[ Eagle PCB ] 初次洗板
05-21[ Eagle PCB ] Panelize 併板
05-20[ Eagle PCB ] 建立自己的Library及元件
05-20[ Eagle PCB ] 添加library及元件
05-20[ Eagle PCB ] Introduce

2018

04-25[ TCP test Tool ] 好用的TCP Server/Client工具
01-16RZ/A1H -[0]- Renesas RZ/A1H YR0K77210S009BE BSP環境架設

2017

12-11EZ USB Suit使用JLink online debug FX3
10-20RL78 -[12]- CS+_CACX_Lab5_LowPower mode
10-16RL78 -[11]- CS+_CACX_Lab4_ADC_溫度感測
10-13RL78 -[10]- CS+_CACX_Lab4_ADC_內部參考電壓
10-13RL78 -[9]- CS+_Lab3_I2C + MPU6050
10-13RL78 -[8]- CS+_Lab2_Uart transmit
10-12RL78 -[7]- Renesas Flash Programmer 獨立燒錄軟體
10-12RL78 -[6]- CS+_雜記
10-12RL78 -[5]- CS+_tracking variables on debug mode
10-12RL78 -[4]- CS+_顯示ROM與RAM的使用size
10-12RL78 -[3]- CS+_Lab1_Led blinking
10-12RL78 -[2]- CS+專案建立
10-12RL78 -[1]- 開發環境介紹
10-06ESP-01 -[0]- 硬體設置
10-06LinkIt 7688 program Renesas RL78/G12 by 1-wire
10-06LinkIt Smart 7688 -[3]- Build the firmware from source codes
10-06LinkIt Smart 7688 -[2]- 使用UART進入bootloader / kernel console
10-06LinkIt Smart 7688 -[1]- 使用SSH連接kernel console
10-06LinkIt Smart 7688 -[0]- 初次使用
07-14LinkIt Smart 7688 -[9]- Using MRAA SPI in Python
07-13LinkIt Smart 7688 -[8]- Using MRAA UART in Python
07-12LinkIt Smart 7688 -[7]- Using MRAA I2C in Python
07-12LinkIt Smart 7688 -[6]- Using MRAA PWM in Python
07-12LinkIt Smart 7688 -[5]- Using MRAA GPIO in Python
07-10LinkIt Smart 7688 -[4]- 雜記
06-29輕乳酪蛋糕 Cotton Cheesecake
06-26VirtualBox 的 Ubuntu與Windows 共用資料夾

2015

04-29偵測USB PnP