这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » DIY与开源设计 » 电子DIY » 过程贴手势与HID功能

共3条 1/1 1 跳转至

过程贴手势与HID功能

工程师
2024-07-12 10:54:07     打赏


使用STM32H5控制PAJ7620U2实现虚拟键盘枚举与手势控制的功能,大致进行的几个步骤:硬件连接、软件设置、手势识别与映射、虚拟键盘枚举以及功能测试。

以下是详细解释:

一、硬件连接连接PAJ7620U2模块:将PAJ7620U2模块通过I2C接口连接到STM32H5开发板上。PAJ7620U2模块会提供SCL(时钟线)和SDA(数据线)两个引脚,需要连接到STM32H5的相应I2C接口上。确保模块的供电电压与STM32H5的I/O电压兼容,一般为3.3V。连接USB接口:

使用一根USB Type-C数据线连接STM32H5开发板的另一个USB口到电脑上,用于模拟虚拟键盘。

image.png

二、软件设置配置STM32H5的I2C接口:

在STM32CubeMX或HAL库中配置I2C接口的相关参数,时钟频率等。

image.png


配置USB HID设备:在STM32CubeMX中启用USB HID设备功能,描述符等。

image.png


image.png

三、手势识别与映射手势识别:使用PAJ7620U2模块提供的手势识别功能,通过I2C接口读取手势数据。根据PAJ7620U2的数据手册或模块的技术文档,解析手势数据,识别出用户的手势。手势映射:将识别出的手势映射到相应的界面上。
/**  
 * @brief 填充HID事件以反映手势按键的状态  
 * @param hid_event 指向HID事件结构体的指针,用于存储手势按键的数据  
 *  
 * 此函数根据当前的手势按键类型(`gesture_key.type`),填充HID事件结构体中的缓冲区和长度字段。  
 * HID事件用于通过USB HID类设备报告按键或手势的状态。  
 */  
static void Gesture_GetKeyData(UX_SLAVE_CLASS_HID_EVENT *hid_event)  
{  
    // 设置HID事件的总长度为8字节(假设)  
    // 注意:实际长度可能需要根据HID报告描述符进行调整  
    hid_event->ux_device_class_hid_event_length = 8;  
  
    // 初始化HID事件缓冲区的前两个字节为0,可能用于保留或其他用途  
    hid_event->ux_device_class_hid_event_buffer[0] = 0;  
    hid_event->ux_device_class_hid_event_buffer[1] = 0;  
  
    // 检查是否有手势按键被激活  
    if (gesture_key.type)  
    {  
        // 根据手势按键的类型,设置HID事件缓冲区中的相应字节  
        switch (gesture_key.type)  
        {  
        case PAJ_UP: // 上  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x52; // 假设0x52是对应“上”的按键码  
            break;  
        case PAJ_DOWN: // 下  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x51; // 假设0x51是对应“下”的按键码  
            break;  
        case PAJ_LEFT: // 左  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x50; // 假设0x50是对应“左”的按键码  
            break;  
        case PAJ_RIGHT: // 右  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x4F; // 假设0x4F是对应“右”的按键码  
            break;  
        case PAJ_FORWARD:  
            // 此处未设置任何值,可能需要添加对应的前进操作或忽略  
            break;  
        case PAJ_BACKWARD:  
            // 同上,可能需要添加对应的后退操作或忽略  
            break;  
        case PAJ_CLOCKWISE:  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x3E; // 假设0x3E是对应顺时针旋转的按键码  
            break; // 注意注释中的F5可能是误导,实际应依据按键码表  
        case PAJ_COUNT_CLOCKWISE:  
            hid_event->ux_device_class_hid_event_buffer[2] = 0x29; // 假设0x29是对应逆时针旋转的按键码  
            break; // 同样,ESC可能是误导  
        case PAJ_WAVE:  
            // 挥手动作可能不直接映射到按键码,这里设置为0表示无按键按下  
            hid_event->ux_device_class_hid_event_buffer[2] = 0;  
            break;  
        default:  
            // 默认情况下不执行任何操作  
            break;  
        }  
    }  
  
    // 注意:此函数只修改了HID事件缓冲区的一个字节(索引为2),  
    // 其他字节(如索引3-7)保持未初始化状态,这可能不是预期的行为。  
    // 根据HID报告描述符,您可能需要填充这些字节以符合设备的期望。  
}

四、虚拟键盘枚举

编写虚拟键盘枚举代码:在STM32的USB HID设备代码中,实现虚拟键盘的枚举功能。这通常涉及到修改USB描述符,并编写相应的代码来模拟键盘的输入。

当手势被识别并映射到相应的按键时,通过USB HID接口将按键信息发送给电脑。将STM32H5开发板连接到电脑上,运行测试程序。执行手势操作,观察电脑是否接收到相应的键盘输入。

/**  
 * @brief USB HID键盘设备的主线程入口点  
 * @param thread_input 线程输入参数,这里未使用  
 *  
 * 此函数在USB HID键盘设备的上下文中运行,负责检测手势按键事件并通过HID类发送相应的键盘码。  
 */  
static VOID usbx_hidkeyboard_thread_entry(ULONG thread_input)  
{  
    /* USER CODE BEGIN app_ux_device_thread_entry */  
      
    /* 指向USB从设备结构体的指针 */  
    UX_SLAVE_DEVICE *device;  
      
    /* 用于存储HID事件的结构体 */  
    UX_SLAVE_CLASS_HID_EVENT hid_event;  
      
    /* 忽略未使用的线程输入参数 */  
    TX_PARAMETER_NOT_USED(thread_input);  
      
    /* 获取USB从设备结构体的地址 */  
    device = &_ux_system_slave->ux_system_slave_device;  
      
    /* 初始化HID事件结构体,将所有字节设置为0 */  
    ux_utility_memory_set(&hid_event, 0, sizeof(UX_SLAVE_CLASS_HID_EVENT));  
      
    /* 无限循环,等待并处理手势按键事件 */  
    while (1)  
    {  
        /* 检查设备是否已配置,并且HID键盘实例是否有效 */  
        if ((device->ux_slave_device_state == UX_DEVICE_CONFIGURED) && (hid_keyboard != UX_NULL))  
        {  
            /* 休眠10毫秒,减少CPU占用 */  
            tx_thread_sleep(MS_TO_TICK(100)); // 注意:这里原始代码是100毫秒,注释中写的是10ms  
              
            /* 检查是否有有效的手势按键事件 */  
            if (gesture_key.valid != 0)  
            {  
                /* 标记手势按键为已处理 */  
                gesture_key.valid = 0;  
                  
                /* 调用函数填充HID事件结构体 */  
                Gesture_GetKeyData(&hid_event);  
                  
                /* 发送HID事件到HID键盘实例 */  
                ux_device_class_hid_event_set(hid_keyboard, &hid_event);  
            }  
            else  
            {  
                /* 如果没有手势按键事件,则清除HID事件结构体(如果需要的话) */  
                ClearKeyData(&hid_event); // 注意:这个函数需要您自己实现,用于清除HID事件数据  
                  
                /* 发送空的HID事件到HID键盘实例,可能用于通知没有按键被按下 */  
                ux_device_class_hid_event_set(hid_keyboard, &hid_event);  
            }  
        }  
        else  
        {  
            /* 如果设备未配置或HID键盘实例无效,则休眠较短的时间 */  
            tx_thread_sleep(MS_TO_TICK(10)); // 休眠10毫秒  
        }  
    }  
    /* USER CODE END app_ux_device_thread_entry */  
}
/**  
 * @brief 激活或初始化HID键盘设备  
 * @param hid_instance 指向HID类的实例的指针,该实例代表HID键盘  
 *  
 * 此函数接收一个指向HID类的实例的指针,并将其存储在全局变量hid_keyboard中,  
 * 以便在USB HID键盘设备的处理函数中使用。  
 */  
VOID USBD_HID_Keyboard_Activate(VOID *hid_instance)  
{  
    /* USER CODE BEGIN USBD_HID_Keyboard_Activate */  
      
    // 注意:UX_PARAMETER_NOT_USED是一个宏,用于防止编译器警告未使用的参数  
    // 如果你确实需要使用这个参数,就不要注释掉这行代码  
    // UX_PARAMETER_NOT_USED(hid_instance);  
      
    // 将传入的HID实例指针转换为UX_SLAVE_CLASS_HID*类型,并存储在hid_keyboard中  
    // 假设hid_keyboard已经在其他地方被声明为全局或静态变量  
    hid_keyboard = (UX_SLAVE_CLASS_HID*)hid_instance;  
      
    /* USER CODE END USBD_HID_Keyboard_Activate */  
  
    // 函数返回,不需要执行其他操作  
    return;  
}
五、功能测试请见汇总贴



高工
2024-07-12 11:54:46     打赏
2楼

谢谢分享


高工
2024-07-13 08:57:44     打赏
3楼

谢谢分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]