周所周知,#STM32 有著板載#USB 接口,之前我們利用STM32的USB實現(xiàn)VCP(虛擬串口)來代替原始串口實現(xiàn)串口。
但是USB的功能還有很多很多,本期我們來介紹利用STM32的USB實現(xiàn)鼠標輸入功能。
硬件平臺采用STM32F407ZGT6
1、HID
#HID(Human Interface Device)全稱#人機接口設備,是一類允許人類與計算機進行交互的設備。我們常用的鼠標、鍵盤、觸摸屏都屬于HID設備。它定義了輸入/輸出數(shù)據(jù)的格式和協(xié)議,不需要專用驅動就能識別。
例如目前在用的鼠標接入電腦時,系統(tǒng)會將其識別為HID鼠標。
HID設備以中斷方式與主機通信,定時上報數(shù)據(jù)主機通過GetReport/SetReport與設備進行數(shù)據(jù)交互數(shù)據(jù)采用HID報告(HIDReport)格式,描述鼠標移動、按鍵狀態(tài)等
要在STM32中實現(xiàn)鼠標輸入,就是STM32作為主機HOST來獲取鼠標設備的HIDReport。下面介紹#CubeMX?的配置和部分代碼。
2、CubeMX配置
首先開啟一組USART用來輸出調試信息,接著開啟USB_OTG_FS功能,模式選擇為主機模式(Host_Only)。
由于對USB設備的性能要求不高,因此不用選擇USB_OTG_HS而選擇FS即可。
在拓展包中的USB_HOST中,為FS選擇HID設備。
對于下方的HID配置詳細解釋如下:
條目 | 作用 |
USBH_MAX_NUM_ENDPOINTS | USB 接口支持的最大端點 |
USBH_MAX_NUM_INTERFACES | 每個 USB 設備支持的最大接口
數(shù)量 |
USBH_MAX_NUM_SUPPORTED_CLASS | 最大 USB 設備類數(shù)量 |
USBH_MAX_NUM_CONFIGURATION | USB 主機庫支持的最大配置數(shù)量 |
USBH_KEEP_CFG_DESCRIPTOR | 保留 USB 設備的配置描述符 |
USBH_MAX_SIZE_CONFIGURATION | 設備配置描述符最大允許大小 |
USBH_MAX_DATA_BUFFER | 主機庫在內(nèi)存中分配的數(shù)據(jù)緩沖區(qū)的最大大小 |
USBH_DEBUG_LEVEL | 調試信息的輸出級別 |
這里其他的都選擇默認配置,只有最后的調試信息輸出級別,推薦使用級別2.
而且需要注意的是,USB庫的調試信息使用printf輸出,這要求我們對系統(tǒng)進行串口重定向。大家可以參考#串口重定向?那期的文章基于HAL庫和CubeMX的STM32 串口通信以及重定向?(點擊連接跳轉)。
由于我的板子需要單獨開啟USB電源,因此需要開啟一個GPIO來作為USB電源控制。
將一個GPIO設置為OutPut模式之后,同樣的可以在USB_HOST中配置電源控制為GPIO:Output。
3、時鐘要求
這個晶振時鐘也是在CubeMX中配置的,但是這里要單獨強調一下,否則會導致工作失敗。
USB正常工作要求時鐘為48MHZ,但是CubeMX默認工程中大家需要注意修改HSE外部高速時鐘的輸入和自己芯片的實際輸入是否一致,否則可能會導致工作失敗。
4、文件結構和使用
CubeMX生成工程之后會出現(xiàn)USB主機庫,這里是不需要我們修改什么東西的,大家把目光著重放到main.c中。
? while (1)
? {
? ??/* USER CODE END WHILE */
? ? MX_USB_HOST_Process();
? ??/* USER CODE BEGIN 3 */
? }
這個函數(shù)是處理 USB 主機的狀態(tài)機和相關事件,是 USB 主機庫運行機制的核心部分,負責推進 USB 主機的狀態(tài)機,使主機能夠在不同狀態(tài)之間切換,如未初始化、已初始化、已連接設備、已配置設備等,確保能根據(jù)設備連接狀態(tài)執(zhí)行相應的操作。
接著我們在頭文件中包含下面這個頭文件
#include"usbh_hid.h"
之后我們編寫鼠標回調函數(shù):
voidUSBH_HID_EventCallback(USBH_HandleTypeDef *phost)
{
? ? HID_MOUSE_Info_TypeDef *mouse_info = USBH_HID_GetMouseInfo(phost);
if?(mouse_info != NULL)
? ? {
printf("X: %dtY: %dtButtons: L:%d M:%d R:%drn",
? ? ? ? ? ? ? ?mouse_info->x,
? ? ? ? ? ? ? ?mouse_info->y,
? ? ? ? ? ? ? ?mouse_info->buttons[0],
? ? ? ? ? ? ? ?mouse_info->buttons[1],
? ? ? ? ? ? ? ?mouse_info->buttons[2]);
? ? }
}
每當我們運動鼠標的時候,這個中斷回調函數(shù)就會觸發(fā),因此我們可以獲得鼠標運動狀態(tài)。
4、鼠標屏幕相結合
我們在回調函數(shù)中將鼠標運動狀態(tài)累加起來就可以得到鼠標的位置了,接下來我們設置一下當按下鼠標左鍵時候,可以在屏幕中畫圖。按下鼠標右鍵的時候可以清空畫布。