STM32H5 的 USBD Classic 驱动 CDC 移植核心是 “复用 HID 工程框架 + 替换 CDC 相关文件 + 解决接口注册与驱动适配”,可避开 USBX 的 OS 依赖,实现裸机环境下的虚拟串口通信。移植关键在于补全缺失的驱动文件、屏蔽 USB PD 干扰、正确配置 PMA 与描述符、注册 CDC 接口,按步骤操作即可解决枚举失败、驱动安装报错、HardFault 等常见问题。
1. 核心概述
1.1 移植背景与目标
- 痛点:STM32CubeMX 6.9.1 对 STM32H5 仅默认支持 USBX(依赖 Threadx OS),缺乏裸机 Classic USB CDC 例程;
- 资源基础:STM32H5 的 Classic USB HID 例程(GitHub 开源)可作为移植框架,需替换为 CDC 类相关文件;
- 移植目标:实现裸机 Classic USB CDC 功能,设备枚举为虚拟串口,支持双向通信,兼容 Windows 默认驱动。
1.2 必备资源清单
- 基础工程:GitHub 仓库
stm32h5-classic-coremw-apps(含 HID 例程); - 依赖库:STM32CubeH5 HAL 库(含 Drivers 文件夹)、
stm32_mw_usb_device(USB Device Library); - 参考例程:STM32U5 的 Classic USB CDC 例程(用于替换描述符与接口文件)。
2. 移植前准备
- 下载并解压
stm32h5-classic-coremw-apps,补全缺失文件:- 拷贝 STM32CubeH5 的
Drivers文件夹(含 BSP、CMSIS、HAL_Driver)到工程目录; - 下载
stm32_mw_usb_device,拷贝Core和Class/CDC文件夹到Middlewares/ST/STM32_USB_Device_Library;
- 拷贝 STM32CubeH5 的
- 编译原始 HID 工程,验证基础环境:确保 HID 设备能正常枚举(鼠标功能可用),排除硬件与 HAL 库问题。
3. 详细移植步骤(按优先级排序)
3.1 屏蔽 USB PD 功能(避免干扰)
USB PD 与 Classic USB 无耦合,仅因 Type-C 接口协议要求存在,裸机移植需移除:
- 删除工程中
STM32_USBPD_Library文件夹; - 屏蔽
main.c和usb_device.c中所有 USB PD 相关代码,简化主函数:int main(void) { HAL_Init(); SystemClock_Config(); MX_USB_Device_Init(); while(1) {} } - 在
MX_USB_Device_Init()中添加USBD_Start(原由 PD 功能调用,移除后手动添加):void MX_USB_Device_Init(void) { // 初始化USB设备库、添加类 if (USBD_Init(&hUsbDeviceFS, &CDC_Desc) != USBD_OK) Error_Handler(); if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) Error_Handler(); // 手动添加USBD启动(原由USB PD调用) HAL_PWREx_EnableVddUSB(); USBD_Start(&hUsbDeviceFS); }
3.2 替换 CDC 相关文件
- 移除 HID 相关文件:
usbd_hid.c及对应头文件; - 添加 CDC 核心文件:从
stm32_mw_usb_device/Class/CDC/Src拷贝usbd_cdc.c和usbd_cdc.h到工程; - 添加接口模板文件:拷贝
usbd_cdc_if_template.c和usbd_cdc_if_template.h到工程(提供 CDC 收发回调接口)。
3.3 配置 PMA(数据包存储区)
CDC 与 HID 的端点资源不同,需修改
usbd_conf.c的 PMA 配置(替换原 HID 的 PMA 设置):/* USER CODE BEGIN EndPoint_Configuration */
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData, 0x00, PCD_SNG_BUF, 0x20); // 控制端点IN
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData, 0x80, PCD_SNG_BUF, 0x40); // 控制端点OUT
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData, CDC_IN_EP, PCD_SNG_BUF, 0x60); // CDC IN端点
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData, CDC_OUT_EP, PCD_SNG_BUF, 0x80); // CDC OUT端点
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData, CDC_CMD_EP, PCD_SNG_BUF, 0x100); // CDC命令端点
/* USER CODE END EndPoint_Configuration */
3.4 替换 CDC 描述符
- 从 STM32U5 的 CDC 例程中拷贝
usbd_desc.c和usbd_desc.h,替换工程中原 HID 的描述符文件; - 修改
usb_device.c中描述符引用:将&HID_Desc改为&CDC_Desc(与新描述符结构体名称一致)。
3.5 注册 CDC 接口并初始化
- 在
MX_USB_Device_Init()中添加 CDC 接口注册(关键步骤,否则会触发 HardFault):if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_CDC_Template_fops) != USBD_OK) Error_Handler(); - 在
usbd_cdc_if_template.c的TEMPLATE_Init()中添加缓冲区初始化:static int8_t TEMPLATE_Init(void) { USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBuffer, 0); USBD_CDC_SetRxBuffer(&hUsbDeviceFS, UserRxBuffer); return 0; }
3.6 解决驱动安装报错(Code 10)
- 调整工程
icf文件(IAR)或ld文件(GCC)的堆大小,建议设置为0x1000(避免内存不足); - 确保
usbd_cdc_if_template.c中的回调函数(TEMPLATE_Init、TEMPLATE_Receive)正确实现,无语法错误。
4. 移植验证:CDC 通信测试
- 编译工程并下载到 STM32H5 开发板(如 NUCLEO-H563Z);
- 连接 USB Type-C 线到 PC,设备管理器应识别 “USB Serial Device (COMx)”,无黄色感叹号;
- 使用串口助手测试:
- 发送数据(如 “666666”),设备应回显相同数据;
- 测试不同长度数据(≤64 字节),验证通信稳定性。
5. 避坑关键要点
- 驱动文件缺失:确保
Drivers和STM32_USB_Device_Library文件完整,否则编译报错 “missing rule to make file”; - USB PD 干扰:未屏蔽 PD 功能会导致
USBD_Start未调用,设备无法枚举; - PMA 配置错误:CDC 端点地址与 PMA 缓冲区地址不匹配,会导致数据收发失败;
- 接口未注册:遗漏
USBD_CDC_RegisterInterface,会触发 HardFault; - 堆大小不足:默认堆太小会导致驱动安装失败(Code 10),需扩大堆空间;
- 描述符不匹配:未替换 CDC 描述符,会导致枚举为未知设备。
STM32H5 USBD Classic 驱动 CDC 移植的核心是 “复用 HID 框架 + 替换 CDC 组件 + 解决接口与资源适配”,关键步骤包括补全驱动文件、屏蔽 PD 干扰、配置 PMA、替换描述符、注册接口。按流程操作可快速实现裸机 CDC 功能,满足虚拟串口通信需求,无需依赖 USBX 操作系统。
阅读全文
314