首页 自动驾驶

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战

分类:自动驾驶
字数: (9753)
阅读: (2360)
内容摘要:STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战,

在嵌入式开发中,STM32 USB HID 设备的应用非常广泛,尤其是在一些需要简单人机交互的场景。最近在做一个项目,需要将一个基于 LAT1466 的 STM32 USB HID 设备,从原有的复杂系统独立出来,作为一个 standalone 应用运行。过程中遇到了不少坑,特此记录。

LAT1466 简介与问题场景

LAT1466 并非一个标准的 STM32 外设或库,而是指某些特定厂商或项目中使用的一种自定义的 USB 接口或者模块,其 HID (Human Interface Device) 功能允许设备通过 USB 接口模拟键盘、鼠标等输入设备,实现与上位机的通信。我们遇到的问题是:原工程依赖大量的底层库和中间件,体积庞大,不适合作为一个独立的 HID 设备应用。

问题:依赖复杂,资源占用高

原工程为了实现各种功能,集成了 FreeRTOS、LWIP 等重量级组件。但我们的 HID 设备只需要简单的 USB 通信功能,这些组件完全是多余的。此外,原工程的代码结构复杂,耦合度高,难以分离出 HID 设备相关的代码。

问题:USB 描述符配置不清晰

LAT1466 相关的 USB 描述符配置分散在多个文件中,难以理解和修改。特别是 HID 报告描述符,定义了设备与上位机之间的数据传输格式,稍有不慎就会导致设备无法正常工作。

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战

底层原理深度剖析

要解决上述问题,我们需要深入理解 STM32 USB HID 设备的工作原理,以及 USB 协议的相关知识。

USB HID 协议

USB HID 协议定义了设备与主机之间的通信方式,包括设备描述符、配置描述符、接口描述符、端点描述符和 HID 描述符。其中,HID 报告描述符最为关键,它定义了设备与主机之间的数据传输格式。

STM32 USB 中断处理

STM32 通过 USB 外设的中断来处理 USB 事件,例如设备连接、数据接收和数据发送。我们需要编写中断服务程序(ISR)来处理这些事件,并更新设备的状态。

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战

端点配置

USB 通信通过端点进行,每个端点都有一个唯一的地址和传输类型。HID 设备通常使用中断端点进行数据传输,以保证数据的实时性。

解决方案与代码示例

下面我们将逐步介绍如何将 LAT1466 的 STM32 USB HID 设备独立出来,作为一个 standalone 应用运行。

步骤 1:创建独立工程

首先,我们需要创建一个新的 STM32 工程,只包含必要的启动代码、时钟配置和 USB 外设初始化代码。可以使用 STM32CubeIDE 或其他开发工具创建工程。

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战

步骤 2:移植 USB 驱动

将原工程中与 USB HID 设备相关的驱动代码移植到新工程中。这些代码通常包括 USB 初始化函数、中断服务程序、数据接收和发送函数。

步骤 3:精简 USB 描述符

仔细分析原工程中的 USB 描述符,删除不必要的字段,并确保 HID 报告描述符的正确性。下面是一个简化的 HID 报告描述符示例:

/* HID report descriptor */
__ALIGN_BEGIN static uint8_t USBD_HID_ReportDesc[USBD_HID_REPORT_DESC_SIZE] __ALIGN_END =
{
 0x05, 0x01,                    // USAGE_PAGE (Generic Desktop)
 0x09, 0x06,                    // USAGE (Keyboard)
 0xA1, 0x01,                    // COLLECTION (Application)
 0x05, 0x07,                    // USAGE_PAGE (Keyboard/Keypad)
 0x19, 0xE0,                    // USAGE_MINIMUM (Keyboard LeftControl)
 0x29, 0xE7,                    // USAGE_MAXIMUM (Keyboard Right GUI)
 0x15, 0x00,                    // LOGICAL_MINIMUM (0)
 0x25, 0x01,                    // LOGICAL_MAXIMUM (1)
 0x75, 0x01,                    // REPORT_SIZE (1)
 0x95, 0x08,                    // REPORT_COUNT (8)
 0x81, 0x02,                    // INPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
 0x95, 0x01,                    // REPORT_COUNT (1)
 0x75, 0x08,                    // REPORT_SIZE (8)
 0x81, 0x01,                    // INPUT (Cnst,Var,Abs)
 0x95, 0x05,                    // REPORT_COUNT (5)
 0x75, 0x01,                    // REPORT_SIZE (1)
 0x05, 0x08,                    // USAGE_PAGE (LEDs)
 0x19, 0x01,                    // USAGE_MINIMUM (Num Lock)
 0x29, 0x05,                    // USAGE_MAXIMUM (Kana)
 0x91, 0x02,                    // OUTPUT (Data,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
 0x95, 0x01,                    // REPORT_COUNT (1)
 0x75, 0x03,                    // REPORT_SIZE (3)
 0x91, 0x01,                    // OUTPUT (Cnst,Var,Abs,No Wrap,Linear,Preferred State,No Null Position)
 0x95, 0x06,                    // REPORT_COUNT (6)
 0x75, 0x08,                    // REPORT_SIZE (8)
 0x05, 0x07,                    // USAGE_PAGE (Keyboard/Keypad)
 0x19, 0x00,                    // USAGE_MINIMUM (Reserved (no event indicated))
 0x29, 0x65,                    // USAGE_MAXIMUM (Keyboard Application)
 0x81, 0x00,                    // INPUT (Data,Ary,Abs)
 0xC0                          // END_COLLECTION
};

步骤 4:编写主循环

在主循环中,我们需要不断地检测 USB 连接状态,并处理接收到的数据。下面是一个简单的主循环示例:

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战
int main(void)
{
 /* MCU Configuration--------------------------------------------------------*/

 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
 HAL_Init();

 /* Configure the system clock */
 SystemClock_Config();

 /* Initialize USB device */
 USBD_Init(&hUsbDeviceFS, &FS_Desc, 0);

 /* Register HID class */
 USBD_RegisterClass(&hUsbDeviceFS, &USBD_HID);

 /* Start device */
 USBD_Start(&hUsbDeviceFS);

 /* Infinite loop */
 while (1)
 {
 // 检测 USB 连接状态
 if (hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED) {
 // 处理接收到的数据
 }
 }
}

实战避坑经验总结

避免使用 HAL 库的默认配置

HAL 库的默认配置可能不适合我们的应用,需要仔细检查并修改。

仔细阅读 STM32 的 USB 参考手册

STM32 的 USB 参考手册包含了大量的技术细节,是解决问题的关键。

使用 USB 分析仪

USB 分析仪可以帮助我们抓取 USB 数据包,分析通信过程,快速定位问题。

注意中断优先级

确保 USB 中断的优先级高于其他中断,以保证 USB 通信的实时性。

通过以上步骤,我们可以将 LAT1466 的 STM32 USB HID 设备独立出来,作为一个 standalone 应用运行。这个过程需要耐心和细致,但最终可以提高代码的可维护性和可移植性。在实际操作中,还需要根据具体情况进行调整,例如优化代码结构、改进 USB 描述符等。希望这篇文章能帮助大家解决类似的问题。

STM32 USB HID 设备独立应用移植:LAT1466 踩坑实战

转载请注明出处: 键盘上的咸鱼

本文的链接地址: http://m.acea5.store/blog/080352.SHTML

本文最后 发布于2026-04-10 23:45:58,已经过了16天没有更新,若内容或图片 失效,请留言反馈

()
您可能对以下文章感兴趣
评论
  • 螺蛳粉真香 4 天前
    USB 分析仪是神器!之前用逻辑分析仪搞了半天没搞明白,换了 USB 分析仪一下就找到了问题。