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