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_WritePinHAL_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的备用功能