在上个帖子完成了手势传感器PAJ7620U2数据的读取,本帖就基于此配置了USB HID鼠标,并利用传感器数据实现手势控制。
使用STM32CubeMX 可以方便的建立 STM32 USB HID 的项目,官方支持了ThreadX全家桶的USBX,功能非常强大。
系统框图如下:
手势传感器模块通过I2C接口与STM32H503单片机通信,STM32H503单片机通过USB接口与电脑通信,模拟一个USB HID免驱动的设备----鼠标,利用手势输出不同的鼠标控制指令。
下面介绍stm32cubemx配置USB HID鼠标的方法。
app_usbx_device.c代码:
/* USER CODE BEGIN Header */ /** ****************************************************************************** * @file app_usbx_device.c * @author MCD Application Team * @brief USBX Device applicative file ****************************************************************************** * @attention * * Copyright (c) 2024 STMicroelectronics. * All rights reserved. * * This software is licensed under terms that can be found in the LICENSE file * in the root directory of this software component. * If no LICENSE file comes with this software, it is provided AS-IS. * ****************************************************************************** */ /* USER CODE END Header */ /* Includes ------------------------------------------------------------------*/ #include "app_usbx_device.h" /* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include "usb.h" #include "DEV_Config.h" #include "PAJ7620U2.h" /* USER CODE END Includes */ /* Private typedef -----------------------------------------------------------*/ /* USER CODE BEGIN PTD */ /* USER CODE END PTD */ /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ /* USER CODE END PD */ /* Private macro -------------------------------------------------------------*/ /* USER CODE BEGIN PM */ /* USER CODE END PM */ /* Private variables ---------------------------------------------------------*/ static ULONG hid_keyboard_interface_number; static ULONG hid_keyboard_configuration_number; static UX_SLAVE_CLASS_HID_PARAMETER hid_keyboard_parameter; static TX_THREAD ux_device_app_thread; /* USER CODE BEGIN PV */ static TX_THREAD ux_hid_read_thread; /* USER CODE END PV */ /* Private function prototypes -----------------------------------------------*/ static VOID app_ux_device_thread_entry(ULONG thread_input); /* USER CODE BEGIN PFP */ static VOID usbx_hidkeyboard_thread_entry(ULONG thread_input); VOID USBX_APP_Device_Init(VOID); /* USER CODE END PFP */ /** * @brief Application USBX Device Initialization. * @param memory_ptr: memory pointer * @retval status */ UINT MX_USBX_Device_Init(VOID *memory_ptr) { UINT ret = UX_SUCCESS; UCHAR *device_framework_high_speed; UCHAR *device_framework_full_speed; ULONG device_framework_hs_length; ULONG device_framework_fs_length; ULONG string_framework_length; ULONG language_id_framework_length; UCHAR *string_framework; UCHAR *language_id_framework; UCHAR *pointer; TX_BYTE_POOL *byte_pool = (TX_BYTE_POOL*)memory_ptr; /* USER CODE BEGIN MX_USBX_Device_Init0 */ /* USER CODE END MX_USBX_Device_Init0 */ /* Allocate the stack for USBX Memory */ if (tx_byte_allocate(byte_pool, (VOID **) &pointer, USBX_DEVICE_MEMORY_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) { /* USER CODE BEGIN USBX_ALLOCATE_STACK_ERROR */ return TX_POOL_ERROR; /* USER CODE END USBX_ALLOCATE_STACK_ERROR */ } /* Initialize USBX Memory */ if (ux_system_initialize(pointer, USBX_DEVICE_MEMORY_STACK_SIZE, UX_NULL, 0) != UX_SUCCESS) { /* USER CODE BEGIN USBX_SYSTEM_INITIALIZE_ERROR */ return UX_ERROR; /* USER CODE END USBX_SYSTEM_INITIALIZE_ERROR */ } /* Get Device Framework High Speed and get the length */ device_framework_high_speed = USBD_Get_Device_Framework_Speed(USBD_HIGH_SPEED, &device_framework_hs_length); /* Get Device Framework Full Speed and get the length */ device_framework_full_speed = USBD_Get_Device_Framework_Speed(USBD_FULL_SPEED, &device_framework_fs_length); /* Get String Framework and get the length */ string_framework = USBD_Get_String_Framework(&string_framework_length); /* Get Language Id Framework and get the length */ language_id_framework = USBD_Get_Language_Id_Framework(&language_id_framework_length); /* Install the device portion of USBX */ if (ux_device_stack_initialize(device_framework_high_speed, device_framework_hs_length, device_framework_full_speed, device_framework_fs_length, string_framework, string_framework_length, language_id_framework, language_id_framework_length, UX_NULL) != UX_SUCCESS) { /* USER CODE BEGIN USBX_DEVICE_INITIALIZE_ERROR */ return UX_ERROR; /* USER CODE END USBX_DEVICE_INITIALIZE_ERROR */ } /* Initialize the hid keyboard class parameters for the device */ hid_keyboard_parameter.ux_slave_class_hid_instance_activate = USBD_HID_Keyboard_Activate; hid_keyboard_parameter.ux_slave_class_hid_instance_deactivate = USBD_HID_Keyboard_Deactivate; hid_keyboard_parameter.ux_device_class_hid_parameter_report_address = USBD_HID_ReportDesc(INTERFACE_HID_KEYBOARD); hid_keyboard_parameter.ux_device_class_hid_parameter_report_length = USBD_HID_ReportDesc_length(INTERFACE_HID_KEYBOARD); hid_keyboard_parameter.ux_device_class_hid_parameter_report_id = UX_FALSE; hid_keyboard_parameter.ux_device_class_hid_parameter_callback = USBD_HID_Keyboard_SetReport; hid_keyboard_parameter.ux_device_class_hid_parameter_get_callback = USBD_HID_Keyboard_GetReport; /* USER CODE BEGIN HID_KEYBOARD_PARAMETER */ /* USER CODE END HID_KEYBOARD_PARAMETER */ /* Get hid keyboard configuration number */ hid_keyboard_configuration_number = USBD_Get_Configuration_Number(CLASS_TYPE_HID, INTERFACE_HID_KEYBOARD); /* Find hid keyboard interface number */ hid_keyboard_interface_number = USBD_Get_Interface_Number(CLASS_TYPE_HID, INTERFACE_HID_KEYBOARD); /* Initialize the device hid keyboard class */ if (ux_device_stack_class_register(_ux_system_slave_class_hid_name, ux_device_class_hid_entry, hid_keyboard_configuration_number, hid_keyboard_interface_number, &hid_keyboard_parameter) != UX_SUCCESS) { /* USER CODE BEGIN USBX_DEVICE_HID_KEYBOARD_REGISTER_ERROR */ return UX_ERROR; /* USER CODE END USBX_DEVICE_HID_KEYBOARD_REGISTER_ERROR */ } /* Allocate the stack for device application main thread */ if (tx_byte_allocate(byte_pool, (VOID **) &pointer, UX_DEVICE_APP_THREAD_STACK_SIZE, TX_NO_WAIT) != TX_SUCCESS) { /* USER CODE BEGIN MAIN_THREAD_ALLOCATE_STACK_ERROR */ return TX_POOL_ERROR; /* USER CODE END MAIN_THREAD_ALLOCATE_STACK_ERROR */ } /* Create the device application main thread */ if (tx_thread_create(&ux_device_app_thread, UX_DEVICE_APP_THREAD_NAME, app_ux_device_thread_entry, 0, pointer, UX_DEVICE_APP_THREAD_STACK_SIZE, UX_DEVICE_APP_THREAD_PRIO, UX_DEVICE_APP_THREAD_PREEMPTION_THRESHOLD, UX_DEVICE_APP_THREAD_TIME_SLICE, UX_DEVICE_APP_THREAD_START_OPTION) != TX_SUCCESS) { /* USER CODE BEGIN MAIN_THREAD_CREATE_ERROR */ return TX_THREAD_ERROR; /* USER CODE END MAIN_THREAD_CREATE_ERROR */ } /* USER CODE BEGIN MX_USBX_Device_Init1 */ /* Allocate the stack for usbx hid thread */ if (tx_byte_allocate(byte_pool, (VOID **) &pointer, 1024, TX_NO_WAIT) != TX_SUCCESS) { return TX_POOL_ERROR; } /* Create the usbx hid thread */ if (tx_thread_create(&ux_hid_read_thread, "hid_acm_read_usbx_app_thread_entry", usbx_hidkeyboard_thread_entry, 1, pointer, 1024, 20, 20, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) { return TX_THREAD_ERROR; } /* USER CODE END MX_USBX_Device_Init1 */ return ret; } /** * @brief Function implementing app_ux_device_thread_entry. * @param thread_input: User thread input parameter. * @retval none */ static VOID app_ux_device_thread_entry(ULONG thread_input) { /* USER CODE BEGIN app_ux_device_thread_entry */ //TX_PARAMETER_NOT_USED(thread_input); USBX_APP_Device_Init(); /* USER CODE END app_ux_device_thread_entry */ } /* USER CODE BEGIN 1 */ unsigned char PAJ7620U2_init() { unsigned char i,State; DEV_Set_I2CAddress(PAJ7620U2_I2C_ADDRESS); DEV_Delay_ms(5); State = DEV_I2C_ReadByte(0x00); //Read State if (State != 0x20) return 0; //Wake up failed DEV_I2C_WriteByte(PAJ_BANK_SELECT, 0); //Select Bank 0 for (i=0;i< Init_Array;i++) { DEV_I2C_WriteByte(Init_Register_Array[i][0], Init_Register_Array[i][1]);//Power up initialize } return 1; } int ReadGesture() { return DEV_I2C_ReadWord(PAJ_INT_FLAG1); } static VOID usbx_hidkeyboard_thread_entry(ULONG thread_input) { /* USER CODE BEGIN app_ux_device_thread_entry */ printf("Gesture Sensor Test Program ...\r\n"); while(!PAJ7620U2_init()) { printf("\nGesture Sensor Error\r\n"); HAL_Delay(500); } printf("\nGesture Sensor OK\r\n"); DEV_I2C_WriteByte(PAJ_BANK_SELECT, 0); //Select Bank 0 for (int i = 0; i < Gesture_Array_SIZE; i++) { DEV_I2C_WriteByte(Init_Gesture_Array[i][0], Init_Gesture_Array[i][1]);//Gesture register initializes } UX_SLAVE_DEVICE *device; UX_SLAVE_CLASS_HID_EVENT hid_event; TX_PARAMETER_NOT_USED(thread_input); device = &_ux_system_slave->ux_system_slave_device; ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT)); while(1) { /* Check if the device state already configured */ if((device->ux_slave_device_state == UX_DEVICE_CONFIGURED) && (hid_keyboard != UX_NULL)) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); tx_thread_sleep(MS_TO_TICK(100)); hid_event.ux_device_class_hid_event_length = 8; hid_event.ux_device_class_hid_event_buffer[0] = 0; hid_event.ux_device_class_hid_event_buffer[1] = 0; uint16_t Gesture_Data = ReadGesture(); if(Gesture_Data != 0) { switch (Gesture_Data) { case PAJ_UP: hid_event.ux_device_class_hid_event_buffer[2] = 0x4B; break; //Keyboard PageUp case PAJ_DOWN: hid_event.ux_device_class_hid_event_buffer[2] = 0x4E; break; //Keyboard PageDown case PAJ_LEFT: hid_event.ux_device_class_hid_event_buffer[2] = 0x50; break; //Keyboard LeftArrow case PAJ_RIGHT: hid_event.ux_device_class_hid_event_buffer[2] = 0x4F; break; //Keyboard RightArrow case PAJ_FORWARD: hid_event.ux_device_class_hid_event_buffer[2] = 0x4A; break; //Keyboard Home case PAJ_BACKWARD: hid_event.ux_device_class_hid_event_buffer[2] = 0x4D; break; //Keyboard End case PAJ_CLOCKWISE: hid_event.ux_device_class_hid_event_buffer[2] = 0x3E; break; //Keyboard F5 //case PAJ_ANTI_CLOCKWISE: hid_event.ux_device_class_hid_event_buffer[2] = 0x29; break; //Keyboard Esc case PAJ_WAVE: break; default: break; } ux_device_class_hid_event_set(hid_keyboard, &hid_event); } else { hid_event.ux_device_class_hid_event_buffer[2] = 0; ux_device_class_hid_event_set(hid_keyboard, &hid_event); } } else { tx_thread_sleep(MS_TO_TICK(10)); } HAL_Delay(100); } /* USER CODE END app_ux_device_thread_entry */ } VOID USBX_APP_Device_Init(VOID) { /* USER CODE BEGIN USB_Device_Init_PreTreatment_0 */ /* USER CODE END USB_Device_Init_PreTreatment_0 */ /* initialize the device controller HAL driver */ MX_USB_PCD_Init(); /* USER CODE BEGIN USB_Device_Init_PreTreatment_1 */ HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x00, PCD_SNG_BUF, 0x14); HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x80, PCD_SNG_BUF, 0x54); HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x81, PCD_SNG_BUF, 0x94); HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x01, PCD_SNG_BUF, 0xD4); HAL_PCDEx_PMAConfig(&hpcd_USB_DRD_FS, 0x82, PCD_SNG_BUF, 0x114); /* USER CODE END USB_Device_Init_PreTreatment_1 */ /* Initialize and link controller HAL driver */ ux_dcd_stm32_initialize((ULONG)USB_DRD_FS, (ULONG)&hpcd_USB_DRD_FS); /* Start the USB device */ HAL_PCD_Start(&hpcd_USB_DRD_FS); /* USER CODE BEGIN USB_Device_Init_PostTreatment */ /* USER CODE END USB_Device_Init_PostTreatment */ } /* USER CODE END 1 */
使用锤子在线鼠标键盘测试工具进行测试,
https://www.toolhelper.cn/Keyboard/KeyboardTest
效果: