STM32 USB虚拟串口CDC_Receive_FS回调未触发问题求助
STM32 USB CDC无法触发
CDC_Receive_FS回调排查方案 按优先级从高到低排查,90%的同类问题由前两项配置错误导致:
1. 确认已手动开启CDC接收
STM32CubeMX生成的USB CDC驱动默认不会自动启动OUT端点接收,必须手动提交接收缓冲区,否则端点不会响应主机下发的数据,自然不会触发接收回调:
- 打开
usbd_cdc_if.c文件,在CDC_Init_FS函数中补充接收启动逻辑,默认生成的该函数为空:
// 全局静态分配接收缓冲区,长度不要小于CDC_DATA_FS_MAX_PACKET_SIZE(默认64字节) static uint8_t cdc_rx_buf[64]; static int8_t CDC_Init_FS(void) { USBD_CDC_SetTxBuffer(&hUsbDeviceFS, UserTxBufferFS, 0); USBD_CDC_SetRxBuffer(&hUsbDeviceFS, cdc_rx_buf); // 关键:提交接收请求,激活端点接收 USBD_CDC_ReceivePacket(&hUsbDeviceFS); return USBD_OK; }
- 注意:每次
CDC_Receive_FS执行完成后,必须重新调用USBD_CDC_SetRxBuffer和USBD_CDC_ReceivePacket提交新的接收请求,否则回调只会触发一次,后续数据无法接收。你的点灯测试代码可以放在该函数最开头验证:
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { // 测试逻辑 HAL_GPIO_WritePin(LD1_GPIO_Port, LD1_Pin, GPIO_PIN_SET); // 数据处理逻辑写在这里 // 重新提交接收 USBD_CDC_SetRxBuffer(&hUsbDeviceFS, cdc_rx_buf); USBD_CDC_ReceivePacket(&hUsbDeviceFS); return USBD_OK; }
2. 确认USB时钟配置符合要求
USB OTG FS对时钟精度要求极高,必须输出精准的48MHz时钟,误差超过±0.25%就会导致枚举失败或传输异常:
- 打开Clock Configuration页,确认USB OTG FS的时钟源为PLL48CLK,配置PLLQ分频得到48MHz时钟
- 确认HSE晶振参数和开发板实际硬件匹配:NUCLEO-F746ZG板载HSE为8MHz,不要误配置为其他开发板常用的25MHz
- 不要使用HSI作为USB时钟源,HSI精度不满足USB规范要求,大概率导致通信异常
3. 确认中断配置正确
- NVIC配置中,
USB On The Go FS global interrupt的优先级必须低于SysTick优先级(优先级数值大于SysTick的优先级值,例如SysTick优先级设为0,USB中断设为5),否则中断内调用的HAL库超时逻辑会卡死,导致设备无法正常工作 - 确认
stm32f7xx_it.c中OTG_FS_IRQHandler函数正确调用了HAL_PCD_IRQHandler(&hpcd_USB_OTG_FS),中断没有被屏蔽
4. 确认硬件连接与枚举状态正常
- 先验证设备枚举是否正常:插上USB线后,主机系统能识别到
STMicroelectronics Virtual COM Port设备,无驱动异常。如果枚举失败,优先检查VBUS配置:- NUCLEO-F746ZG的USB FS VBUS检测引脚为PA9,若开启VBUS检测功能,需确认PA9正确连接到USB接口VBUS引脚,没有被其他外设占用
- 不需要VBUS检测的话可以直接在USB OTG FS配置中关闭VBUS功能,避免电平检测异常导致设备不启动
- 确认USB线插在开发板的USB USER接口(CN13,直连MCU的USB引脚),不是ST-Link对应的USB接口(CN1),ST-Link自带的虚拟串口和你实现的USB CDC是完全独立的设备
- USB CDC是虚拟串口,通信和你设置的9600/921600波特率没有实际关联,不需要反复调整波特率测试
5. 排查外设冲突
- 你配置的TIM2外设引脚为PA0-PA3,和USB使用的PA11(DM)/PA12(DP)没有冲突,只要没有把PA11、PA12分配给其他功能即可
- 确认主循环中没有长时间关闭中断、阻塞式延时超过10ms的逻辑,避免USB中断无法及时响应
内容的提问来源于stack exchange,提问作者Ardakaniz
相关产品推荐
相关产品推荐

