一、项目概述
本次参加手势翻页的项目,主要是实现如何驱动STM32H503的USB来模拟键盘或者鼠标,通过获取PAJ7620U2的隔空手势来实现对PC的外设驱动。本次项目使用了六个手势,分别为左、右、上、下扫,以及下压、抬起。对应的模拟键盘为:
PAJ_UP-------------Keyboard PageUp
PAJ_DOWN--------Keyboard PageDown
PAJ_LEFT-----------Keyboard LeftArrow
PAJ_RIGHT---------Keyboard RightArrow
PAJ_FORWARD---- Keyboard Home
PAJ_BACKWAR-----Keyboard End
本项目的重点与难点为如何驱动HID设备。
二、开发环境
1、MDK5.39
2、STM32CubeMAX6.2.0
三、开发硬件
2、PAJ7620U2 手势传感器 Grove 平台评估扩展板
四、开发步骤
1、使用stm32cubeMAX新建一个基于stm32H503RBTx的工程。
2、开启I2C1配置,IO为PB7、PB6,速率为400K快速模式:

3、打开外部晶振输入:

并配置总线时种为250M,并确认USB的总线时钟为48M

4、打开THREADX,并按下图配置相关配置。因为USBX需要TheadX来实现多任务系统。在配置中,我们主要配置时钟,是否创建ThreadX任务,以及配置ThreadX内存空间。

5、打开USB,配置为Device_Only模式,打开中断,GPIO选择PA12、PA13。

6、打开USBX,按下图依次选择。

配置USBX参数如下:

【注意】特别要注意第3与第4,如果分配太小,会出现在运行中挂机。

这些参数需要阅读USBX协议才能明白,我也是根据其他的大佬的文章来设置的。
接着打开参数,设置为USB

7、接打开工程设置中的高级配置,把下面两个选项钩选:

8、调整中断级别如下:

9、配置按外设生成单个的代码。

最后生成代码。就可以使用MDK来打开工程了。
【用户代码】
以上的工程创建,还不能驱动HID。还需要添加用户的代码。
1、打ux_device_keyboard.c,添加hid_keyboard并在函数中初始化。

2、打开app_usbx_device.c添加一个任务,代码如下:
/* 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 */代码主要是动态创建任务,并指定hid_acm_read_usbx_app_thread_entry为入口函数。
3、添加PAJ7620驱动到工程中:

驱动我在前面的帖子里有介绍:【换取手持数字示波器】STM32U083实现手势识别功能-电子产品世界论坛 (eepw.com.cn)
4、将头文件加入到ux_device_keyboard.c中。同时编译获取手势状到,并更新到HID发送函数中,其代码如下:
static VOID usbx_hidkeyboard_thread_entry(ULONG thread_input)
{
/* USER CODE BEGIN app_ux_device_thread_entry */
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));
PAJ7620U2_init();
while(1)
{
/* Check if the device state already configured */
if ((device->ux_slave_device_state == UX_DEVICE_CONFIGURED) && (hid_keyboard != UX_NULL))
{
/* sleep for 10ms */
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;
int Gesture_Data = PAJ7620U2_Gesture_ReadData();
if( Gesture_Data != PAJ_NONE )
{
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; // Keyboard Home
break;
case PAJ_BACKWARD: hid_event.ux_device_class_hid_event_buffer[2] = 0x4A; // Keyboard End
break;
case PAJ_CLOCKWISE:
break;
case PAJ_ANTI_CLOCKWISE:
break;
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
{
/* sleep for 10ms */
tx_thread_sleep(MS_TO_TICK(10));
}
}
/* USER CODE END app_ux_device_thread_entry */
}5、最后需要添加自定义的初始化函数:
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 */
}其代码意思大家可以查阅相关资料,说实在话,我也没有弄明白。希望有大佬给科普一下。
然后将此函数添加工程任务初始化中:

到用户代码编写结束,主要是添加一个任务,创建任务入口函数,任务周期读取手势传感器的数据,并按USB 键盘的规则组装数据,并发送给上位机。
同时还需要添加USB_HID的初始化代码。
视频链接:https://www.bilibili.com/video/BV1NZ421g7GM/?pop_share=1
我要赚赏金
