如何解决STM32F103 Blue Pill板MCU复位后USB VCP功能失效问题
STM32F103 Blue Pill开发板USB VCP复位后失效问题
我正在尝试解决基于STM32F103的Blue Pill开发板上USB VCP功能在微控制器复位(例如烧录新代码后)无法正常工作的问题。
当前状态下,VCP初始运行正常,但硬件复位后PuTTY无法再接收到VCP发送的新数据,不过连接到UART1的FTDI适配器仍可正常工作。以下是精简版的main.c代码:
#include "main.h" #include "usb_device.h" #include <string.h> #include <usbd_cdc_if.h> // 避免CDC_Transmit_FS()出现"隐式声明函数"警告 int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART1_UART_Init(); MX_USB_DEVICE_Init(); char msg[50]; HAL_StatusTypeDef ret_status = HAL_OK; sprintf(msg, "Reset!\n"); ret_status = HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); uint8_t state = 0; while (1) { HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, state ? GPIO_PIN_RESET : GPIO_PIN_SET); sprintf(msg, "Hello World! LED State: %d\n", state); ret_status = HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY); ret_status = CDC_Transmit_FS((uint8_t*)msg, strlen(msg)); HAL_Delay(500); state = state == 1 ? 0 : 1; } }
我查阅相关技术资料了解到,该问题大概率是因为D+线路从未被拉低,导致主机未识别到从设备已复位*(因此需要重新初始化)*。但我不清楚该在哪里如何应用修复方案。我尝试在MX_USB_DEVICE_Init()函数中插入一对HAL_GPIO_WritePin和HAL_Delay指令,代码如下:
void MX_USB_DEVICE_Init(void) { /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET); HAL_Delay(100); /* USER CODE END USB_DEVICE_Init_PreTreatment */ /* 初始化设备库,添加支持的类并启动库 */ if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) { Error_Handler(); } if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { Error_Handler(); } if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { Error_Handler(); } if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { Error_Handler(); } /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ /* USER CODE END USB_DEVICE_Init_PostTreatment */ }
但该操作没有效果。我还尝试将引脚拉取电平改为GPIO_PIN_RESET,避免自己搞错逻辑低电平对应的常量,依旧没有效果。按我的推理这应该能实现预期的修复效果,看来我对问题的理解有误,请问有人知道该如何解决这个问题吗?
解决方案(2021年10月22日)
根据社区技术回答的指导,我修改了MX_USB_DEVICE_Init()函数,添加对应代码后的最终代码如下:
void MX_USB_DEVICE_Init(void) { /* USER CODE BEGIN USB_DEVICE_Init_PreTreatment */ GPIO_InitTypeDef GPIO_InitStruct = {0}; /* 配置GPIO引脚输出电平 */ HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); /* 配置GPIO引脚:PA12 */ GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET); HAL_Delay(100); // 经我测试实际不需要,可直接删除,不会产生不良影响 /* USER CODE END USB_DEVICE_Init_PreTreatment */ /* 初始化设备库,添加支持的类并启动库 */ if (USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS) != USBD_OK) { Error_Handler(); } if (USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC) != USBD_OK) { Error_Handler(); } if (USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS) != USBD_OK) { Error_Handler(); } if (USBD_Start(&hUsbDeviceFS) != USBD_OK) { Error_Handler(); } /* USER CODE BEGIN USB_DEVICE_Init_PostTreatment */ /* USER CODE END USB_DEVICE_Init_PostTreatment */ }
该代码是我参考STM32CubeMX生成的Blue Pill板绿色贴片LED(PC13)配置代码改编而来。对我而言,该修改可实现MCU复位后VCP恢复正常工作,不过PuTTY仍会报错,需要手动重新初始化连接。
内容的提问来源于stack exchange,提问作者ifconfig
相关产品推荐
相关产品推荐

