Bài viết này trình bày về tính năng USB Human Interface Device (USB HID) trên MCU STM32F103C8T6 với việc giả lập MCU thành chuột máy tính với 4 nút nhấn (nút click phải, nút click trái, nút di chuyển xuống, nút di chuyển qua phải). Trước khi bắt đầu project, chúng ta hãy cùng tìm hiểu USB là gì rồi mới đến cách thực hiện chức năng USB HID trên STM32F103C8T6.
[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
Giới thiệu
USB (Universal Serial Bus) là chuẩn truyền thông nối tiếp để đảm bảo các kết nối tiêu chuẩn cho các thiết bị Plug and Play (cắm và chạy) như: bàn phím, chuột, các đầu đọc thẻ nhớ, máy in…
Để dễ dàng phân biệt các thiết bị cắm vào máy tính người ta chia thành các lớp USB như sau:
Phân lớp thiết bị | Miêu tả | Thiết bị ví dụ |
0x00 | (không dùng) | |
0x01 | USB audio device | Soundcard (card âm thanh) |
0x02 | USB communications device | Modem, fax |
0x03 | USB human interface device | Keyboard, mouse |
0x07 | USB printer device | Máy in |
0x08 | USB mass storage device (USB Thiết bị lưu trữ ) | Memory card, flash drive |
0x09 | USB hub device | Hubs |
0x0B | USB smart card reader device ( USB Thiết bị đọc thẻ thông minh) | Card reader (bộ đọc thẻ nhớ) |
0x0E | USB video device ( USB Thiết bị Video) | Webcam, scanner |
0xE0 | USB wireless device ( USB Thiết bị wireless) | Bluetooth |
Xem chi tiết tại đây
Mô tả chức năng USB trong STM32F103C8T6
– Hỗ trợ chuẩn USB 2.0
– Tốc độ kết nối qua USB ở chế độ Full Speed (FS) là 12Mbps, còn ở chế độ Low Speed (LS) là 1.5Mbps.
– Sơ đồ khối ngoại vi USB của STM32
USB endpoints
– Endpoint là thuật ngữ liên quan đến phần cứng trong thiết bị USB, thực chất endpoint là một bộ đệm để có thể truyền/nhận dữ liệu.
– Mỗi endpoint đi kèm với khối mô tả chứa các thông tin: địa chỉ của endpoint trong bộ nhớ, kích thước endpoint và số byte truyền đi.
– Khi 1 tín hiệu cho endpoint được phát hiện thì dữ liệu sẽ được truyền đi và nạp vào thanh ghi 16 bit (Endpoint registers), đồng thời việc truy cập bộ nhớ vào Packet buffer được thực hiện. Tại cuối transaction, một ngắt sẽ được sinh ra giúp MCU phát hiện endpoint nào thực hiện transaction và biết lỗi nếu xảy ra (lỗi format, thiếu ACK, …).
– Khối Interrupt Mapper có một chức năng đáng quan tâm đó là USB wakeup interrupt. Chức năng này dùng để đánh thức thiết bị khi đang ở trong chế độ low-power mode.
Tính năng USB human interface device class của USB
HID (Human Interface Device): là một phân lớp trong tiêu chuẩn USB. Một thiết bị HID có thể được lập trình để định nghĩa lại chức năng của nó. Thiết bị HID trong bài viết này là một chuột máy tính.
Lớp USB human interface device giúp việc thao tác trên các thiết bị trở nên dễ dàng. Các thiết bị định nghĩa các gói dữ liệu của nó (bao gồm các thông tin thiết bị hỗ trợ bao nhiêu gói dữ liệu, kích thước mỗi gói và mục đích của mỗi byte trong dữ liệu), sau đó gửi đến Host.
CubeMX setup
Bước 1:
– Ở mục USB_DEVICE chọn Human Interface Device Class
– Ở mục RCC chọn Crystal/Ceramic Resonator để chọn bộ thạch anh ngoại
– Mục SYS, chọn Serial Wire để nạp code và debug
– Mục USB, chọn Device (FS)
– Chọn các chân PA0, PA1, PA2, PA3 làm input
Bước 2: Thiết lập clock cho MCU
Bước 3: Cấu hình project và sinh code
– Chọn Project Manager -> Project -> đặt tên cho Project.
– Ở Toolchain /IDE chọn MDK-ARM V5
Bước 4: Generate code
Keil C uVision
Trước khi bắt đầu vào code, các bạn build chương trình rồi load vào kit. Sau khi load xong, kiểm tra xem thử máy tính đã nhận được cổng ảo hay chưa bằng cách:
– Kích chuột phải vào This PC chọn Manage -> Device Manager -> Mice and other pointing devices -> HID-compliant mouse. Vì chương trình mặc định là sử dụng USB HID Mouse nên nếu máy tính nhận được port của MCU thì sẽ xuất hiện HID-compliant mouse.
Chương trình thực hiện:
– Đầu tiên ta include thư viện “usbd_hid.h”
1 2 |
/* USER CODE BEGIN Includes */ #include "usbd_hid.h" |
– Sau đó define các biến cần dùng
1 2 3 4 5 6 7 8 9 10 11 |
/* USER CODE BEGIN PV */ /* Private variables ---------------------------------------------------------*/ #define REPORT_SIZE 5 #define RIGHT_CLICK_GPIO GPIOA #define RIGHT_CLICK_PIN GPIO_PIN_0 #define LEFT_CLICK_GPIO GPIOA #define LEFT_CLICK_PIN GPIO_PIN_1 #define VER_MOTION_GPIO GPIOA #define VER_MOTION_PIN GPIO_PIN_2 #define HOR_MOTION_GPIO GPIOA #define HOR_MOTION_PIN GPIO_PIN_3 |
– Khai báo mảng click_report[] gồm 5 phần tử để gửi tọa độ của mouse pointer hoặc trạng thái click chuột:
1 |
uint8_t click_report[REPORT_SIZE] = {0}; |
– Mở file usb_device.c và tìm đến USBD_HandleTypeDef hUsbDeviceFS, copy và extern dòng đó vào file main. c
0 |
extern USBD_HandleTypeDef hUsbDeviceFS; |
– Khai báo hàm getPointerData() ở /* USER CODE BEGIN PFP */
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 |
void getPointerData(void) { static uint8_t button = 0; if(HAL_GPIO_ReadPin(RIGHT_CLICK_GPIO, RIGHT_CLICK_PIN) == GPIO_PIN_RESET) { button = 2; } else { button = 0; } if(HAL_GPIO_ReadPin(LEFT_CLICK_GPIO, LEFT_CLICK_PIN) == GPIO_PIN_RESET) { button = 1; } if(HAL_GPIO_ReadPin(VER_MOTION_GPIO, VER_MOTION_PIN) == GPIO_PIN_RESET) { y++; } else { y = 0; } if(HAL_GPIO_ReadPin(HOR_MOTION_GPIO, HOR_MOTION_PIN) == GPIO_PIN_RESET) { x++; } else { x = 0; } click_report[0] = button; //click click_report[1] = x; //x click_report[2] = y; //y click_report[3] = 0; //wheel click_report[4] = 0; //motion wakeup } |
– Tại USER CODE BEGIN 3:
1 2 3 4 5 6 7 8 9 10 |
while (1) { /* USER CODE END WHILE */ /* USER CODE BEGIN 3 */ HAL_Delay(100); getPointerData(); USBD_HID_SendReport(&hUsbDeviceFS,click_report,5); } /* USER CODE END 3 */ |
Link video demo:
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.
Nhóm TAPIT ARM R&D