在上个帖子完成了手势传感器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
效果:

框图被吞了。
我要赚赏金
