STM32 USB开发详解:CDC虚拟串口与HID键盘鼠标(基于CubeUSB库)

前言:STM32的USB功能为何重要?

在嵌入式开发中,设备与外界通信的方式多种多样(UART、SPI、I2C等),但USB凭借"即插即用"、"高速传输"和"供电能力"三大优势,成为设备与PC/手机通信的首选方案。STM32大部分中高端型号(如F103C8T6、F407IGH6、L431RCT6等)都集成了USB外设,支持从机、主机或OTG模式,可实现虚拟串口、键盘、鼠标等多种功能。

本文聚焦STM32 USB的两种最常用类型:CDC类(虚拟串口)HID类(键盘/鼠标) ,基于ST官方的CubeUSB库(即STM32CubeUSB middleware),从硬件原理、CubeMX配置、代码解析到实战案例,手把手教你实现STM32与PC的USB通信。无论你是需要通过USB传输数据(CDC),还是模拟输入设备(HID),本文都能提供完整的解决方案。

一、STM32 USB硬件基础与CubeUSB库简介

在开始实战前,我们需要先了解STM32 USB的硬件基础和开发工具,为后续开发铺路。

1.1 STM32 USB外设核心特性

STM32的USB外设(以最常用的USB 2.0 Full-Speed为例)具有以下特性:

  • 速度:支持Full-Speed(12Mbps),部分型号(如F4、H7)支持High-Speed(480Mbps);
  • 模式:支持从机(Device)、主机(Host)和OTG(On-The-Go)模式,本文聚焦从机模式;
  • 端点:最多支持8个双向端点(Endpoint),用于数据传输(控制、批量、中断、同步传输);
  • 低功耗:支持USB suspend模式,适合电池供电设备。

硬件电路注意 :STM32的USB引脚(通常为PA11(USB_DM)、PA12(USB_DP))需要外接1.5kΩ上拉电阻(DP引脚),部分型号(如F103)内置上拉电阻,可通过软件控制使能。典型电路如下:

复制代码
PA12(USB_DP)→ 1.5kΩ电阻 → 3.3V(上拉)
PA11(USB_DM)→ 直接连接USB母座
USB母座外壳接地,VCC引脚可接5V(用于给外设供电)

1.2 CubeUSB库:简化USB开发的利器

传统USB开发需要手动编写设备描述符、配置描述符和状态机,门槛极高。ST推出的CubeUSB库(集成在STM32Cube生态中)通过以下方式简化开发:

  • 封装底层协议:自动处理USB枚举、数据收发等复杂流程;
  • 支持多种USB类:内置CDC、HID、MSC(存储)等标准类驱动;
  • 与CubeMX无缝集成:通过图形化配置生成初始化代码,无需手动修改寄存器;
  • 跨系列兼容:同一套API支持F1、F4、L4等多个STM32系列。

本文将基于STM32CubeMX 6.6.0CubeUSB库 2.9.0,以STM32F103C8T6(最小系统板)为例,讲解CDC和HID类设备的开发。

二、USB CDC类:虚拟串口(Virtual COM Port)

CDC(Communications Device Class)是USB的一种标准设备类,其核心功能是将USB设备模拟为串口(即"虚拟串口"),使PC通过USB线与设备通信,就像使用传统UART串口一样。

2.1 CDC类的应用场景

CDC虚拟串口因其"无需额外驱动(Windows自带)"和"即插即用"的特性,广泛应用于:

  • 调试信息输出(替代传统UART串口);
  • 设备参数配置(如传感器校准、WiFi配置);
  • 数据透传(如蓝牙模块与PC的USB桥接)。

2.2 CubeMX配置CDC设备步骤

步骤1:新建工程并选择芯片

打开STM32CubeMX,搜索并选择STM32F103C8T6,点击"Start Project"。

步骤2:配置USB时钟

USB外设需要48MHz的专用时钟(USB clock),配置步骤:

  1. 点击"RCC",设置HSE为"Crystal/Ceramic Resonator"(外部晶振);
  2. 点击"Clock Configuration",配置系统时钟树:
    • HSE = 8MHz;
    • PLLMUL = ×9(PLL输出 = 72MHz);
    • USB Prescaler = /1.5(使USB时钟 = 72MHz / 1.5 = 48MHz);
    • 确保"USB"时钟分支显示为48MHz。
步骤3:配置USB从机模式
  1. 点击"Connectivity"→"USB",设置"Mode"为"Device Only"(从机模式);
  2. 勾选"Activate the Full Speed Interface",此时PA11(USB_DM)和PA12(USB_DP)会自动配置为USB功能。
步骤4:配置CDC类
  1. 点击"Middleware"→"USB_DEVICE",在"Class For FS IP"中选择"Communication Device Class (CDC)";
  2. 点击"Configuration",可修改CDC的默认参数(如厂商名称、产品名称):
    • "Manufacturer String":改为"STM32"(可选);
    • "Product String":改为"STM32 CDC Virtual Port"(可选);
    • "Serial Number String":改为"0001"(可选)。
步骤5:生成代码

点击"Project Manager",设置工程名称(如"STM32_CDC")和路径,选择IDE(如"MDK-ARM V5"),最后点击"Generate Code"生成工程。

2.3 CDC代码结构解析

生成的代码中,与CDC相关的核心文件和函数如下:

核心文件
文件路径 功能描述
Core/Src/usbd_conf.c USB设备配置(端点、缓冲区)
Core/Src/usbd_cdc_if.c CDC接口实现(收发函数)
Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Src/usbd_cdc.c CDC类核心驱动
关键函数
  1. 初始化函数MX_USB_DEVICE_Init()

    位于main.c,用于初始化USB外设和CDC类,自动生成无需修改:

    c 复制代码
    void MX_USB_DEVICE_Init(void)
    {
      /* 初始化USB设备库 */
      USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
      /* 添加CDC接口 */
      USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
      /* 初始化CDC接口 */
      USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
      /* 启动USB设备 */
      USBD_Start(&hUsbDeviceFS);
    }
  2. 发送数据函数CDC_Transmit_FS()

    位于usbd_cdc_if.c,用于向PC发送数据(封装了USB端点发送逻辑):

    c 复制代码
    uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
    {
      uint8_t result = USBD_OK;
      /* 检查发送状态 */
      if(USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData)
      {
        if(hcdc->TxState != 0) return USBD_BUSY;
        /* 复制数据到发送缓冲区 */
        USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len);
        /* 启动发送 */
        result = USBD_CDC_TransmitPacket(&hUsbDeviceFS);
      }
      return result;
    }
  3. 接收回调函数CDC_Receive_FS()

    当PC通过虚拟串口发送数据时,该函数会被自动调用(需用户实现数据处理逻辑):

    c 复制代码
    static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
    {
      /* 用户添加数据处理逻辑 */
      printf("收到PC数据:");
      for(uint32_t i=0; i<*Len; i++)
      {
        printf("%02X ", Buf[i]);
      }
      printf("\r\n");
    
      /* 重新使能接收(必须调用,否则只能接收一次) */
      USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
      USBD_CDC_ReceivePacket(&hUsbDeviceFS);
      return (USBD_OK);
    }

2.4 CDC实战:实现"回声"功能

目标:设备收到PC发送的字符串后,自动回传该字符串(即"回声"功能)。

步骤1:修改接收回调函数

usbd_cdc_if.cCDC_Receive_FS中添加回传逻辑:

c 复制代码
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* 回传收到的数据 */
  CDC_Transmit_FS(Buf, *Len);

  /* 重新使能接收 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
}
步骤2:主循环发送测试数据

main.c的主循环中添加周期性发送逻辑:

c 复制代码
int main(void)
{
  /* 初始化 */
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();

  /* 测试字符串 */
  uint8_t test_buf[] = "Hello, CDC Virtual COM!\r\n";
  uint32_t send_cnt = 0;

  while (1)
  {
    /* 每1秒发送一次测试数据 */
    if(send_cnt % 1000 == 0)
    {
      CDC_Transmit_FS(test_buf, sizeof(test_buf)-1);
    }
    HAL_Delay(1);
    send_cnt++;
  }
}
步骤3:编译下载与测试
  1. 编译工程并下载到STM32F103C8T6开发板;
  2. 用USB线连接开发板的USB口(注意:需连接到STM32的USB引脚,而非UART转USB);
  3. PC会自动识别"STM32 CDC Virtual Port",在设备管理器中查看虚拟串口编号(如COM3);
  4. 打开串口助手(如XCOM),设置波特率115200(CDC虚拟串口波特率无实际意义,任意值均可),可看到设备发送的测试字符串;
  5. 在串口助手发送任意字符串,设备会回传该字符串,实现"回声"功能。

2.5 CDC常见问题与解决方案

  1. 设备无法识别

    • 检查USB线是否为"数据传输线"(部分充电线无数据引脚);
    • 确认PA11/PA12引脚连接正确,上拉电阻是否焊接;
    • 检查USB时钟是否为48MHz(最常见问题)。
  2. 发送数据失败

    • 调用CDC_Transmit_FS前检查返回值,若为USBD_BUSY,说明上一次发送未完成,需等待;
    • 单次发送数据长度不超过CDC端点缓冲区大小(默认512字节)。
  3. 接收数据不完整

    • 确保CDC_Receive_FS中调用了USBD_CDC_ReceivePacket(重新使能接收);
    • 长数据需在应用层处理分包(USB底层可能分多次接收)。

三、USB HID类:键盘与鼠标

HID(Human Interface Device)是USB的另一重要设备类,专为人机交互设备设计,如键盘、鼠标、游戏手柄等。HID设备通过"报告描述符"定义数据格式,PC无需额外驱动即可识别。

3.1 HID类的核心特性

  • 即插即用:Windows、Linux、MacOS均内置HID驱动;
  • 低延迟:采用中断传输(Interrupt Transfer),确保实时响应;
  • 灵活的数据格式:通过报告描述符自定义数据结构(如键盘扫描码、鼠标坐标)。

3.2 HID报告描述符:定义设备"语言"

HID设备与PC通信的核心是报告描述符(Report Descriptor),它告诉PC:

  • 设备类型(键盘/鼠标/其他);
  • 数据格式(如键盘有8个字节,包含 modifier 和扫描码);
  • 数据范围(如鼠标X坐标范围-127~127)。

例如,简化的键盘报告描述符(8字节):

c 复制代码
0x05, 0x01,        // Usage Page (Generic Desktop)
0x09, 0x06,        // Usage (Keyboard)
0xA1, 0x01,        // Collection (Application)
0x05, 0x07,        //   Usage Page (Keyboard)
0x19, 0xE0,        //   Usage Minimum (KB LeftControl)
0x29, 0xE7,        //   Usage Maximum (KB 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)
0x95, 0x01,        //   Report Count (1)
0x75, 0x08,        //   Report Size (8)
0x81, 0x03,        //   Input (Cnst,Var,Abs)
0x95, 0x06,        //   Report Count (6)
0x75, 0x08,        //   Report Size (8)
0x15, 0x00,        //   Logical Minimum (0)
0x25, 0xFF,        //   Logical Maximum (255)
0x05, 0x07,        //   Usage Page (Keyboard)
0x19, 0x00,        //   Usage Minimum (Reserved)
0x29, 0xFF,        //   Usage Maximum (FF)
0x81, 0x00,        //   Input (Data,Var,Abs)
0xC0,              // End Collection

3.3 CubeMX配置HID设备步骤

以"键盘"为例,配置步骤与CDC类似,核心差异在"USB_DEVICE"配置:

步骤1:配置USB时钟(同CDC)

确保USB时钟为48MHz,参考2.2节步骤2。

步骤2:配置HID类
  1. 点击"Middleware"→"USB_DEVICE",在"Class For FS IP"中选择"HID Class";
  2. 点击"Configuration",设置HID参数:
    • "HID Usage Page":选择"Generic Desktop"(通用桌面设备);
    • "HID Usage":选择"Keyboard"(键盘)或"Mouse"(鼠标);
    • "HID Report Descriptor Size":设置为报告描述符长度(如键盘为63字节);
    • "HID Report Size":设置单包报告大小(键盘8字节,鼠标3字节)。
步骤3:生成代码

同CDC,生成工程后,HID核心文件为usbd_hid.cusbd_hid_if.c

3.4 HID键盘开发实战

目标:STM32模拟键盘,按开发板上的按键(如PA0)时,向PC发送"Hello World!"。

步骤1:修改HID报告描述符

usbd_hid_if.c中,替换默认报告描述符为键盘描述符:

c 复制代码
__ALIGN_BEGIN uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
  0x05, 0x01,        // Usage Page (Generic Desktop)
  0x09, 0x06,        // Usage (Keyboard)
  0xA1, 0x01,        // Collection (Application)
  0x05, 0x07,        //   Usage Page (Keyboard)
  0x19, 0xE0,        //   Usage Minimum (KB LeftControl)
  0x29, 0xE7,        //   Usage Maximum (KB 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)
  0x95, 0x01,        //   Report Count (1)
  0x75, 0x08,        //   Report Size (8)
  0x81, 0x03,        //   Input (Cnst,Var,Abs)
  0x95, 0x06,        //   Report Count (6)
  0x75, 0x08,        //   Report Size (8)
  0x15, 0x00,        //   Logical Minimum (0)
  0x25, 0xFF,        //   Logical Maximum (255)
  0x05, 0x07,        //   Usage Page (Keyboard)
  0x19, 0x00,        //   Usage Minimum (Reserved)
  0x29, 0xFF,        //   Usage Maximum (FF)
  0x81, 0x00,        //   Input (Data,Var,Abs)
  0xC0               // End Collection
};
步骤2:定义键盘扫描码映射表

USB键盘通过"扫描码"(Scan Code)表示按键,常见字符的扫描码如下(完整表参考USB HID规范):

c 复制代码
#define KEY_A       0x04
#define KEY_B       0x05
#define KEY_C       0x06
#define KEY_D       0x07
#define KEY_E       0x08
#define KEY_F       0x09
#define KEY_G       0x0A
#define KEY_H       0x0B
#define KEY_I       0x0C
#define KEY_J       0x0D
#define KEY_K       0x0E
#define KEY_L       0x0F
#define KEY_M       0x10
#define KEY_N       0x11
#define KEY_O       0x12
#define KEY_P       0x13
#define KEY_Q       0x14
#define KEY_R       0x15
#define KEY_S       0x16
#define KEY_T       0x17
#define KEY_U       0x18
#define KEY_V       0x19
#define KEY_W       0x1A
#define KEY_X       0x1B
#define KEY_Y       0x1C
#define KEY_Z       0x1D
#define KEY_SPACE   0x2C
#define KEY_ENTER   0x28
步骤3:实现键盘数据发送函数

usbd_hid_if.c中添加发送键盘报告的函数:

c 复制代码
/* 发送键盘报告(8字节):modifier(1字节) + reserved(1字节) + 6个扫描码 */
uint8_t HID_Keyboard_Send(uint8_t modifier, uint8_t* keys, uint8_t len)
{
  uint8_t report[8] = {0};
  report[0] = modifier; //  modifier(如0x02表示Shift)
  
  /* 填充扫描码(最多6个) */
  for(uint8_t i=0; i<len && i<6; i++)
  {
    report[2+i] = keys[i];
  }
  
  /* 发送HID报告 */
  return USBD_HID_SendReport(&hUsbDeviceFS, report, 8);
}
步骤4:主循环检测按键并发送数据

配置PA0为输入(上拉),检测按键按下时发送"Hello World!":

c 复制代码
int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();

  /* 按键引脚配置(PA0上拉输入) */
  GPIO_InitTypeDef GPIO_InitStruct = {0};
  GPIO_InitStruct.Pin = GPIO_PIN_0;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* 要发送的字符串:"Hello World!" */
  uint8_t hello_keys[] = {
    KEY_H, KEY_E, KEY_L, KEY_L, KEY_O, // "Hello"
    KEY_SPACE,                         // 空格
    KEY_W, KEY_O, KEY_R, KEY_L, KEY_D, // "World"
    KEY_1,                             // "!"(Shift+1)
    KEY_ENTER                          // 回车
  };

  uint8_t key_idx = 0;
  uint8_t last_state = 1; // 按键初始状态(高电平)

  while (1)
  {
    /* 检测按键(PA0)状态 */
    uint8_t current_state = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_0);
    
    /* 按键按下(下降沿) */
    if(current_state == 0 && last_state == 1)
    {
      if(key_idx < sizeof(hello_keys))
      {
        uint8_t modifier = 0;
        /* 处理Shift键(如"!"需要Shift+1) */
        if(hello_keys[key_idx] == KEY_1)
        {
          modifier = 0x02; // Left Shift
        }
        
        /* 发送当前字符 */
        HID_Keyboard_Send(modifier, &hello_keys[key_idx], 1);
        HAL_Delay(50); // 按键间隔
        
        /* 发送释放状态(所有按键抬起) */
        HID_Keyboard_Send(0, NULL, 0);
        HAL_Delay(50);
        
        key_idx++;
      }
      else
      {
        key_idx = 0; // 循环发送
      }
    }
    
    last_state = current_state;
    HAL_Delay(10); // 消抖
  }
}
步骤5:测试效果
  1. 下载程序到开发板,连接USB线到PC;
  2. PC会识别"USB Input Device"(键盘);
  3. 打开记事本,按下开发板上的PA0按键,会依次输入"Hello World!"并换行。

3.5 HID鼠标开发实战

鼠标与键盘的开发流程类似,核心差异在报告描述符和数据格式(鼠标通常为3字节:X位移、Y位移、按键状态)。

步骤1:鼠标报告描述符
c 复制代码
__ALIGN_BEGIN uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
  0x05, 0x01,        // Usage Page (Generic Desktop)
  0x09, 0x02,        // Usage (Mouse)
  0xA1, 0x01,        // Collection (Application)
  0x09, 0x01,        //   Usage (Pointer)
  0xA1, 0x00,        //   Collection (Physical)
  0x05, 0x09,        //     Usage Page (Button)
  0x19, 0x01,        //     Usage Minimum (Button 1)
  0x29, 0x03,        //     Usage Maximum (Button 3)
  0x15, 0x00,        //     Logical Minimum (0)
  0x25, 0x01,        //     Logical Maximum (1)
  0x75, 0x01,        //     Report Size (1)
  0x95, 0x03,        //     Report Count (3)
  0x81, 0x02,        //     Input (Data,Var,Abs)
  0x75, 0x05,        //     Report Size (5)
  0x95, 0x01,        //     Report Count (1)
  0x81, 0x01,        //     Input (Cnst)
  0x05, 0x01,        //     Usage Page (Generic Desktop)
  0x09, 0x30,        //     Usage (X)
  0x09, 0x31,        //     Usage (Y)
  0x15, 0x81,        //     Logical Minimum (-127)
  0x25, 0x7F,        //     Logical Maximum (127)
  0x75, 0x08,        //     Report Size (8)
  0x95, 0x02,        //     Report Count (2)
  0x81, 0x06,        //     Input (Data,Var,Rel)
  0xC0,              //   End Collection
  0xC0               // End Collection
};
步骤2:鼠标数据发送函数
c 复制代码
/* 鼠标报告:3字节(X位移, Y位移, 按键) */
uint8_t HID_Mouse_Send(int8_t x, int8_t y, uint8_t buttons)
{
  uint8_t report[3] = {x, y, buttons};
  return USBD_HID_SendReport(&hUsbDeviceFS, report, 3);
}
步骤3:主循环控制鼠标移动
c 复制代码
int main(void)
{
  // 初始化代码(略)

  while (1)
  {
    /* 鼠标向右移动(X=10) */
    HID_Mouse_Send(10, 0, 0);
    HAL_Delay(50);
    
    /* 鼠标向下移动(Y=10) */
    HID_Mouse_Send(0, 10, 0);
    HAL_Delay(50);
    
    /* 鼠标向左移动(X=-10) */
    HID_Mouse_Send(-10, 0, 0);
    HAL_Delay(50);
    
    /* 鼠标向上移动(Y=-10) */
    HID_Mouse_Send(0, -10, 0);
    HAL_Delay(50);
    
    /* 左键点击(按下+释放) */
    HID_Mouse_Send(0, 0, 0x01); // 左键按下
    HAL_Delay(200);
    HID_Mouse_Send(0, 0, 0x00); // 左键释放
    HAL_Delay(1000);
  }
}

测试时,PC会识别鼠标,鼠标指针会按上述逻辑移动并点击。

四、CubeUSB库核心API解析

无论是CDC还是HID,CubeUSB库的核心API都围绕"USB设备状态机"和"端点数据传输"设计,掌握这些API可灵活扩展功能。

4.1 USB设备状态机相关函数

函数名 功能描述
USBD_Init() 初始化USB设备(设置描述符)
USBD_RegisterClass() 注册USB设备类(CDC/HID等)
USBD_Start() 启动USB设备(开始枚举)
USBD_Stop() 停止USB设备
USBD_DeInit() 反初始化USB设备

4.2 数据传输相关函数

函数名 功能描述
USBD_CDC_TransmitPacket() CDC类发送数据
USBD_CDC_ReceivePacket() CDC类接收数据(使能端点)
USBD_HID_SendReport() HID类发送报告
USBD_LL_Transmit() 底层端点发送函数(通用)
USBD_LL_Receive() 底层端点接收函数(通用)

4.3 回调函数

CubeUSB库通过回调函数通知应用层USB事件,常见回调包括:

  • USBD_ResetCallback():USB复位事件;
  • USBD_SuspendCallback():USB挂起事件;
  • USBD_ResumeCallback():USB唤醒事件;
  • USBD_CDC_ReceiveCallback():CDC接收数据事件(自定义实现)。

五、HID与CDC的对比及选型建议

特性 CDC类(虚拟串口) HID类(键盘/鼠标)
传输类型 批量传输(Bulk) 中断传输(Interrupt)
数据长度 最大512字节(可配置) 最大64字节(HID规范限制)
延迟 中等(依赖PC调度) 低(1~10ms,中断传输保障)
驱动需求 Windows自带(无需额外驱动) 全平台自带驱动
典型应用 数据透传、调试输出 人机交互设备(键盘、鼠标、手柄)
开发复杂度 低(无需关心报告描述符) 中(需正确定义报告描述符)

选型建议

  • 需传输大量数据(如日志、传感器数据) → 选CDC;
  • 需模拟输入设备(如远程控制、自动化测试) → 选HID;
  • 需跨平台兼容性(Windows/Linux/Mac) → 优先HID。

六、调试USB设备的实用工具

USB开发调试较复杂,推荐以下工具辅助定位问题:

  1. USB设备树查看器(USB Device Tree Viewer)

  2. HID调试工具(HID Terminal)

  3. 串口助手(如XCOM、Putty)

    • 功能:测试CDC虚拟串口的收发功能。
  4. 示波器/逻辑分析仪

    • 功能:测量USB_DP/USB_DM引脚的信号,判断硬件连接是否正常。

七、总结与扩展

本文详细讲解了STM32 USB的两种核心应用:

  • CDC类:通过虚拟串口实现PC与设备的双向数据传输,配置简单,适合数据透传;
  • HID类:通过报告描述符定义数据格式,模拟键盘、鼠标等输入设备,延迟低,适合人机交互。

扩展学习方向

  1. 复合设备:同时支持CDC和HID(如带虚拟串口的游戏手柄);
  2. USB主机模式:STM32作为主机连接U盘、键盘(需用USB Host库);
  3. USB OTG模式:动态切换主机/从机模式(如手机与设备互传数据);
  4. 自定义HID设备:如旋钮、滑块等特殊输入设备,需编写对应的报告描述符。

CubeUSB库极大降低了USB开发的门槛,开发者无需深入理解USB协议细节,即可快速实现各类USB设备。建议从简单的CDC虚拟串口入手,熟悉后再挑战HID设备,逐步掌握STM32 USB开发的精髓。

相关推荐
jacklood2 小时前
基于STM32与中航ZH-E3L字符卡通信在LED屏显示数据
stm32·单片机·嵌入式硬件
wind_one12 小时前
STM32小实验三--让蜂鸣器响起来
stm32·单片机·嵌入式硬件
小憩-2 小时前
【stm32】新建工程
stm32·单片机·嵌入式硬件
wind_one12 小时前
STM32小实验二--流水灯
stm32·单片机·嵌入式硬件
小严家3 小时前
《硬件产品经理》第七章:产品开发流程之验证
嵌入式硬件·产品经理·智能硬件
拼好饭玩家3 小时前
定时器更新中断与串口中断
单片机·嵌入式硬件
LoserChaser6 小时前
STM32新建工程
stm32·单片机·嵌入式硬件
TESmart碲视7 小时前
显示器核心三要素详解:刷新率、分辨率、色深
物联网·游戏·计算机外设·电脑·智能硬件
逼子格7 小时前
共射级放大电路的频率响应Multisim电路仿真——硬件工程师笔记
单片机·嵌入式硬件·硬件工程·硬件工程师·硬件工程师真题·multisim电路仿真·共射级放大电路
沧澜sincerely9 小时前
GPIO 输入/输出
stm32·单片机·嵌入式硬件