STM32Cube USB VCP 在微控制器复位后失效
STM32Cube USB VCP becomes inoperative after microcontroller reset
我正在尝试弄清楚如何使基于 STM32F103 的 Blue Pill 板上的 USB VCP 功能在微控制器复位后运行,例如上传新代码后。
据我所知,VCP 起初运行正常,但在硬件重置后 PuTTY 停止报告来自 VCP 的任何新行。不过,连接到 UART1
的 FTDI 适配器继续工作。这是 main.c
:
的 minified 版本
#include "main.h"
#include "usb_device.h"
#include <string.h>
#include <usbd_cdc_if.h> // Necessary to avoid "warning: implicit declaration of function" for 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;
}
}
在阅读 this SO Q/A 时,我了解到问题可能是由于主机未识别出客户端设备已重置(因此需要重新初始化)因为 D+
线从未被拉下。但是,我不明白 where/how 为此应用修复程序。我尝试在 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 */
/* Init Device Library, add supported class and start the library. */
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
的指令,以防我误解哪个常量对应于逻辑低电平,但它也没有任何效果。据我所知,这应该具有应用 0___________'s answer 中描述的修复的效果,但我一定是误解了这个问题。有谁知道如何解决这个问题?
解决方案(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};
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
/*Configure GPIO pin : 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); // Actually unnecessary (from my testing) and can be removed without consequence.
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
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 的绿色 SMD LED (PC13)。至少对我来说,这使得 VCP 在 MCU 重置后再次运行,尽管 PuTTY 仍然抱怨并且我必须手动重新初始化它。 :)
您的 MX_GPIO_Init 可能会在备用功能模式下初始化 PA11/PA12 引脚以用于 USB 控制器。因此,用 WritePin 将 PA12 拉低将不起作用。
要在 D+ 上强制激活零,首先在 MX_GPIO_Init 之前(或开头)将 PA12 配置为常规 GPIO 输出,并使用代码中编写的 HAL_GPIO_WritePin。比恢复PA12功能作为USB的备用功能
我正在尝试弄清楚如何使基于 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> // Necessary to avoid "warning: implicit declaration of function" for 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;
}
}
在阅读 this SO Q/A 时,我了解到问题可能是由于主机未识别出客户端设备已重置(因此需要重新初始化)因为 D+
线从未被拉下。但是,我不明白 where/how 为此应用修复程序。我尝试在 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 */
/* Init Device Library, add supported class and start the library. */
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
的指令,以防我误解哪个常量对应于逻辑低电平,但它也没有任何效果。据我所知,这应该具有应用 0___________'s answer 中描述的修复的效果,但我一定是误解了这个问题。有谁知道如何解决这个问题?
解决方案(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};
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);
/*Configure GPIO pin : 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); // Actually unnecessary (from my testing) and can be removed without consequence.
/* USER CODE END USB_DEVICE_Init_PreTreatment */
/* Init Device Library, add supported class and start the library. */
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 的绿色 SMD LED (PC13)。至少对我来说,这使得 VCP 在 MCU 重置后再次运行,尽管 PuTTY 仍然抱怨并且我必须手动重新初始化它。 :)
您的 MX_GPIO_Init 可能会在备用功能模式下初始化 PA11/PA12 引脚以用于 USB 控制器。因此,用 WritePin 将 PA12 拉低将不起作用。
要在 D+ 上强制激活零,首先在 MX_GPIO_Init 之前(或开头)将 PA12 配置为常规 GPIO 输出,并使用代码中编写的 HAL_GPIO_WritePin。比恢复PA12功能作为USB的备用功能