前言: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.0 和CubeUSB库 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),配置步骤:
- 点击"RCC",设置HSE为"Crystal/Ceramic Resonator"(外部晶振);
- 点击"Clock Configuration",配置系统时钟树:
- HSE = 8MHz;
- PLLMUL = ×9(PLL输出 = 72MHz);
- USB Prescaler = /1.5(使USB时钟 = 72MHz / 1.5 = 48MHz);
- 确保"USB"时钟分支显示为48MHz。
步骤3:配置USB从机模式
- 点击"Connectivity"→"USB",设置"Mode"为"Device Only"(从机模式);
- 勾选"Activate the Full Speed Interface",此时PA11(USB_DM)和PA12(USB_DP)会自动配置为USB功能。
步骤4:配置CDC类
- 点击"Middleware"→"USB_DEVICE",在"Class For FS IP"中选择"Communication Device Class (CDC)";
- 点击"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类核心驱动 |
关键函数
-
初始化函数 :
MX_USB_DEVICE_Init()
位于
main.c
,用于初始化USB外设和CDC类,自动生成无需修改:cvoid 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); }
-
发送数据函数 :
CDC_Transmit_FS()
位于
usbd_cdc_if.c
,用于向PC发送数据(封装了USB端点发送逻辑):cuint8_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; }
-
接收回调函数 :
CDC_Receive_FS()
当PC通过虚拟串口发送数据时,该函数会被自动调用(需用户实现数据处理逻辑):
cstatic 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.c
的CDC_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:编译下载与测试
- 编译工程并下载到STM32F103C8T6开发板;
- 用USB线连接开发板的USB口(注意:需连接到STM32的USB引脚,而非UART转USB);
- PC会自动识别"STM32 CDC Virtual Port",在设备管理器中查看虚拟串口编号(如COM3);
- 打开串口助手(如XCOM),设置波特率115200(CDC虚拟串口波特率无实际意义,任意值均可),可看到设备发送的测试字符串;
- 在串口助手发送任意字符串,设备会回传该字符串,实现"回声"功能。
2.5 CDC常见问题与解决方案
-
设备无法识别:
- 检查USB线是否为"数据传输线"(部分充电线无数据引脚);
- 确认PA11/PA12引脚连接正确,上拉电阻是否焊接;
- 检查USB时钟是否为48MHz(最常见问题)。
-
发送数据失败:
- 调用
CDC_Transmit_FS
前检查返回值,若为USBD_BUSY
,说明上一次发送未完成,需等待; - 单次发送数据长度不超过CDC端点缓冲区大小(默认512字节)。
- 调用
-
接收数据不完整:
- 确保
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类
- 点击"Middleware"→"USB_DEVICE",在"Class For FS IP"中选择"HID Class";
- 点击"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.c
和usbd_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:测试效果
- 下载程序到开发板,连接USB线到PC;
- PC会识别"USB Input Device"(键盘);
- 打开记事本,按下开发板上的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开发调试较复杂,推荐以下工具辅助定位问题:
-
USB设备树查看器(USB Device Tree Viewer):
- 功能:查看USB设备枚举过程、描述符、端点配置;
- 下载:https://www.uwe-sieber.de/usbtreeview_e.html。
-
HID调试工具(HID Terminal):
- 功能:监控HID设备发送的报告数据,手动发送HID报告;
- 下载:https://github.com/abcminiuser/hidterm。
-
串口助手(如XCOM、Putty):
- 功能:测试CDC虚拟串口的收发功能。
-
示波器/逻辑分析仪:
- 功能:测量USB_DP/USB_DM引脚的信号,判断硬件连接是否正常。
七、总结与扩展
本文详细讲解了STM32 USB的两种核心应用:
- CDC类:通过虚拟串口实现PC与设备的双向数据传输,配置简单,适合数据透传;
- HID类:通过报告描述符定义数据格式,模拟键盘、鼠标等输入设备,延迟低,适合人机交互。
扩展学习方向:
- 复合设备:同时支持CDC和HID(如带虚拟串口的游戏手柄);
- USB主机模式:STM32作为主机连接U盘、键盘(需用USB Host库);
- USB OTG模式:动态切换主机/从机模式(如手机与设备互传数据);
- 自定义HID设备:如旋钮、滑块等特殊输入设备,需编写对应的报告描述符。
CubeUSB库极大降低了USB开发的门槛,开发者无需深入理解USB协议细节,即可快速实现各类USB设备。建议从简单的CDC虚拟串口入手,熟悉后再挑战HID设备,逐步掌握STM32 USB开发的精髓。