哭死!到底做错了哪一步,帖子为啥只剩一半!555
一、在开发板上实现USB HID模拟键盘的功能。
以前只玩过ESP模块的蓝牙模拟键盘鼠标的实验。第一次在STM32上实现通过USB HID模拟键盘功能。参考着论坛帖子一步一步地完成了复现(感谢anger老师)。
1 使用STM32CubeMX进行系统配置。这里需要留意软件的版本号,先前使用了旧版的STM32CubeMX,在配置USBX时,总是没有对应的选项。
需要配置USBX,将USB口添加为键盘。修改USB的缓存。
2 使用STM32CubeMX添加ThreadX。添加实时操作系统threadx,这样就可以使用多任务的方式操作多个外设了。
3 编码实现USB键盘。
系统复位后,首先调用main函数,在main函数中初始化ThreadX,调用MX_ThreadX_Init()方法去启动内核。此时会调用UINT MX_USBX_Device_Init(VOID *memory_ptr) 对USB设备初始化,并且创建一个新任务
static VOID app_ux_device_thread_entry(ULONG thread_input) { /* USER CODE BEGIN app_ux_device_thread_entry */ /* Initialization of USB device */ USBX_APP_Device_Init(); /* USER CODE END app_ux_device_thread_entry */ } /* USER CODE BEGIN 1 */ /** * @brief Function implementing usbx_hidkeyboard_thread_entry. * @param thread_input: User thread input parameter. * @retval none */ 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)); 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)); if (gesture_key.valid != 0) { printf("gesture_key.valid=%d %d\n", gesture_key.valid, gesture_key.type); gesture_key.valid = 0; Gesture_GetKeyData(&hid_event); //发�?�键盘码 ux_device_class_hid_event_set(hid_keyboard, &hid_event); } else { ClearKeyData(&hid_event); 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 */ }
通过这个任务,调用手势传感器获取手势信息,将手势信息映射成键盘码(四个箭头对应的键盘码),并发送给上位机。
二、PAJ7620U2手势传感器的读取。
1 PAJ720U2模块介绍:PAJ720U2手势识别传感器是一款强大的3D手势识别交互式传感器;在最远20cm范围内,最多可以识别13种手势。具备良好的手势识别稳定性和节能机制。就像是模块上有个摄像头,通过获得到的图像数据进行分析,得到手势的类型,并且将结果写入寄存器,通过IIC协议读取寄存器内容,即可获得手势信息。这里反复阅读了页面的介绍这里提供了Arduino下读取PAJ7620的代码,可以用来做参考。
2、PAJ7620U2模块编码:在PAJ7620内部有两个BANK 寄存器区域,分别是BANK0,BANK1。控制着不同的功能。这里唤醒PAJ7620模块后,直接将功能码写入到对应的BANK中去。
unsigned char PAJ7620u2_init(void) { unsigned char status; HAL_Delay(10); status = paj7620u2_wakeup(); //唤醒PAJ7620U2 if (!status) return 0; paj7620u2_selectBank(BANK0); // enter BANK0 HAL_Delay(50); /* Load the registers data */ for (uint8_t i = 0; i < INIT_REG_ARRAY_SIZE; i++) writeReg(initRegisterArray[i][0], initRegisterArray[i][1]); // init PAJ7620U2 paj7620u2_selectBank(BANK0); // enter BANK0 return 1; }
然后去读取寄存器,即可获得PAJ7620U2模块采集到的动作信息。
unsigned char getResult(void) { char buf[16]; char tpcVariable[16]; Gesture_Init(); gesture.detect = PAJ7620_Read_nByte(PAJ_GET_INT_FLAG1, 2, &gesture.data[0]); // 读取手势状态 if (gesture.detect) { gesture.type = (unsigned short)gesture.data[1] << 8 | gesture.data[0]; if (gesture.type) { gesture_key.type = gesture.type; switch (gesture.type) { case GES_UP: printf("Up\r\n"); gesture.valid = 1; gesture_key.valid = 1; break; // case GES_DOWN: printf("Down\r\n"); gesture.valid = 1; gesture_key.valid = 1; break; // case GES_LEFT: printf("Left\r\n"); gesture.valid = 1; gesture_key.valid = 1; break; // case GES_RIGHT: printf("Right\r\n"); gesture.valid = 1; gesture_key.valid = 1; break; // case GES_FORWARD: printf("Forward\r\n"); gesture.valid = 1; break; // case GES_BACKWARD: printf("Backward\r\n"); gesture.valid = 1; break; // case GES_CLOCKWISE: printf("Clockwise\r\n"); gesture.valid = 1; break; // case GES_ANTI_CLOCKWISE: printf("Counterclockwise\r\n"); gesture.valid = 1; break; // case GES_WAVE: printf("Wave\r\n"); gesture.valid = 1; break; // default: gesture.valid = 0; break; } } } return 0; }
三、实现翻页功能。
将获得的手势信息映射为键盘码,这里只映射了4个键盘码:上、下、左、右。上传给电脑,就可以实现在PPT展示时前后的翻页功能了。
static void Gesture_GetKeyData(UX_SLAVE_CLASS_HID_EVENT *hid_event) { 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; if (gesture_key.type) { switch (gesture_key.type) { case GES_UP: hid_event->ux_device_class_hid_event_buffer[2] = 0x52; break; //?? case GES_DOWN: hid_event->ux_device_class_hid_event_buffer[2] = 0x51; break; //?? case GES_LEFT: hid_event->ux_device_class_hid_event_buffer[2] = 0x50; break; //?? case GES_RIGHT: hid_event->ux_device_class_hid_event_buffer[2] = 0x4F; break; //?? case GES_FORWARD: break; case GES_BACKWARD: break; case GES_CLOCKWISE: hid_event->ux_device_class_hid_event_buffer[2] = 0x50; break; //F5 case GES_ANTI_CLOCKWISE: hid_event->ux_device_class_hid_event_buffer[2] = 0x4F; break; //ESC case GES_WAVE: hid_event->ux_device_class_hid_event_buffer[2] = 0; break; // default: break; } } }