Ở bài viết trước các bạn đã được hướng dẫn cách sử dụng kit STM32F103C8T6 như chuột máy tính, trong bài viết này các kiến thức về USB HID sẽ được đi sâu hơn và tính năng USB HID được áp dụng để giả lập SM32F103 thành bàn phím (keyboard).
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
CubeMX generated files
Cài đặt USB HID Keyboard cũng giống với cài đặt cho tính năng USB HID Mouse nên bạn có thể tham khảo ở đây.
Trong thư mục USB device library/Middlewares:
– File usbd_core.c cung cấp tất cả chức năng cốt lõi của thiết bị USB
– Các file usbd_ioreq.c, usbd_ctlreq.c cung cấp các request từ USB IO
– File usbd_hid.c cung cấp các thông tin để tương tác với USB host
Bình thường khi bạn tạo file từ CubeMX thì mặc định các thông số trong file usbd_hid.c là của Mouse USB nên nếu bạn muốn chuyển đổi USB HID Mouse thành USB HID Keyboard thì phải thay đổi các descriptions (mô tả) trong file usbd_hid.c. Cụ thể như sau:
– Ở thư mục Middlewares -> kích đúp chuột vào usbd_hid.c
– Tìm đến mảng USBD_HID_CfgDesc rồi thay đổi các mô tả:
- bInterfaceSubClass: đổi 0x01 thành 0x00 (no boot)
- nInterfaceProtocol: đổi 0x02 thành 0x01 (keyboard)
– Sau đó tìm đến mảng HID_MOUSE_ReportDesc, xóa các thông số có sẵn và thay thế bằng các dòng sau:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
// 78 bytes 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x06, // Usage (Keyboard) 0xA1, 0x01, // Collection (Application) 0x85, 0x01, // Report ID (1) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x75, 0x01, // Report Size (1) 0x95, 0x08, // Report Count (8) 0x19, 0xE0, // Usage Minimum (0xE0) 0x29, 0xE7, // Usage Maximum (0xE7) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0x95, 0x03, // Report Count (3) 0x75, 0x08, // Report Size (8) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x64, // Logical Maximum (100) 0x05, 0x07, // Usage Page (Kbrd/Keypad) 0x19, 0x00, // Usage Minimum (0x00) 0x29, 0x65, // Usage Maximum (0x65) 0x81, 0x00, // Input (Data,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection 0x05, 0x0C, // Usage Page (Consumer) 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x02, // Report ID (2) 0x05, 0x0C, // Usage Page (Consumer) 0x15, 0x00, // Logical Minimum (0) 0x25, 0x01, // Logical Maximum (1) 0x75, 0x01, // Report Size (1) 0x95, 0x07, // Report Count (7) 0x09, 0xB5, // Usage (Scan Next Track) 0x09, 0xB6, // Usage (Scan Previous Track) 0x09, 0xB7, // Usage (Stop) 0x09, 0xB8, // Usage (Eject) 0x09, 0xCD, // Usage (Play/Pause) 0x09, 0xE2, // Usage (Mute) 0x09, 0xE9, // Usage (Volume Increment) 0x09, 0xEA, // Usage (Volume Decrement) 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position) 0xC0, // End Collection |
– Vào Middlewares\ST\STM32_USB_Device_Library\Class\HID\Inc\ usbd_hid.h thay đổi giá trị của các biến
1 2 3 |
#define HID_EPIN_SIZE 0x05 #define HID_MOUSE_REPORT_DESC_SIZE 78 |
– Ở file main.c:
1 2 |
/* USER CODE BEGIN Includes */ #include "usbd_hid.h" |
1 2 3 4 5 |
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ #define PRESS_SIZE 8 #define CHAR_1_GPIO GPIOA #define CHAR_1_PIN GPIO_PIN_0 |
Mở file usb_device.c và tìm đến USBD_HandleTypeDef hUsbDeviceFS, copy và extern dòng đó vào file main.c
1 |
extern USBD_HandleTypeDef hUsbDeviceFS; |
Khai báo mảng press_report để gửi report đến máy tính:
1 |
uint8_t press_report[PRESS_SIZE] = {0}; |
Trong hàm sendData(), nếu bạn nhấn nút PA0 thì trên màn hình máy tính sẽ hiện dòng chữ “abc”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
/* USER CODE BEGIN PFP */ /* Private function prototypes -----------------------------------------------*/ void sendData() { if(HAL_GPIO_ReadPin(GPIOA, CHAR_1_PIN) == GPIO_PIN_RESET) { uint8_t bufferHID[5] = {0, 0, 0, 0, 0}; bufferHID[0] = 1; bufferHID[1] = 0; bufferHID[2] = 0x04; bufferHID[3] = 0x05; bufferHID[4] = 0x06; USBD_HID_SendReport(&hUsbDeviceFS,bufferHID,5); HAL_Delay(100); bufferHID[1] = 0; bufferHID[2] = 0; bufferHID[3] = 0; bufferHID[4] = 0; USBD_HID_SendReport(&hUsbDeviceFS,bufferHID,5); HAL_Delay(100); } } |
Ở vòng while(1), gọi lại hàm sendData()
1 2 3 4 5 6 7 8 9 |
/* USER CODE BEGIN WHILE */ while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ sendData(); } /* USER CODE END 3 */ |
– Link video demo:
Mở rộng
– Dưới đây là mô tả USB HID report cho một thiết bị USB tiêu chuẩn:
1 2 3 4 5 6 7 8 |
USAGE_PAGE (Generic Desktop) USAGE (Device) COLLECTION (Application) USAGE (Pointer) COLLECTION (Physical) ... END COLLECTION END COLLECTION |
– Nếu có nhiều thiết bị USB cùng kết nối thì bạn phải thêm dòng REPORT_ID cho mỗi thiết bị.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
USAGE_PAGE (Generic Desktop) USAGE (Keyboard) COLLECTION (Application) REPORT_ID (1) ... END COLLECTION USAGE_PAGE (Generic Desktop) USAGE (Mouse) COLLECTION (Application) USAGE (Pointer) COLLECTION (Physical) REPORT_ID (2) ... END COLLECTION END COLLECTION USAGE_PAGE (Generic Desktop) USAGE (Game Pad) COLLECTION (Application) COLLECTION (Physical) REPORT_ID (3) ... END COLLECTION END COLLECTION USAGE_PAGE (Generic Desktop) USAGE (Game Pad) COLLECTION (Application) COLLECTION (Physical) REPORT_ID (4) ... END COLLECTION END COLLECTION |
Tham khảo
- Tổng hợp các kiến thức về USB HID Report Descriptors các bạn xem ở đây: https://eleccelerator.com/tutorial-about-usb-hid-report-descriptors
- Keyboard scan codes
Xem thêm: Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32 tại đây.
Ngoc Hang