虚拟串口相关

使用虚拟串口,可以节省板件空间,节省一个串口芯片的钱,哈哈哈

硬件电路

使用PA11(USB_DM)和PA12(USB_DP)作为USB的接口,在电路设计时,要在USB_DP引脚,用1.5KΩ的电阻上拉到3.3V,这样时STM32作为主机。

软件配置

时钟配置

必须使用外部的晶振,才能正确初始化USB的时钟。设置参考如下:

USB初始化

  1. 使用CubeMX开启USB,作基础的设置

  1. 配置USB的相关信息,打开USB_DEVICE,启用VCP即可

Device Descriptor就是串口设备的硬件ID属性

  1. 将对USB的初始化提至最前面,防止工程代码初始化的外设太多,USB的初始化太后至电脑识别失败

构建生成代码,打开编辑器!

代码编辑

在初始化之前,给个适当的延时,当然也可以用硬件电路设计上电顺序,让电源稳定再启动MCU

  /* USER CODE BEGIN SysInit */
  HAL_Delay(1000);
  /* USER CODE END SysInit */

延时可以不加,视情况而定,如果是别失败,加一个试试。参考的解决方法:设别不到USB设备的一种解决方式
这个解决方法也可以用手动模拟插拔

载入程序测试串口

下载程序之后,插拔USB,电脑会识别,进入设备管理器,可以看到新的设备,查看设备的属性 USB\VID_0483&PID_5740&REV_0200与我们设置的是符合的,所以就添加使用成功。

使用USB输出内容

在文件的include区域添加USB的库,#include "usbd_cdc_if.h" // 串口控制 。然后就可以愉快的使用了。

这个是发送的函数:

/**
  * @}
  */

/** @defgroup USBD_CDC_IF_Exported_FunctionsPrototype USBD_CDC_IF_Exported_FunctionsPrototype
  * @brief Public functions declaration.
  * @{
  */

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);

在主循环循环发送:

  while (1)
  {

    CDC_Transmit_FS("Hello World \r\n", strlen("Hello World \r\n"));
    HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }

测试结果:

重定向printf

参考:重定向printf

在usbd_cdc_if.c中,添加如下代码:

/* USER CODE BEGIN PRIVATE_FUNCTIONS_IMPLEMENTATION */
#include <stdarg.h>
 
void usb_printf(const char *format, ...)
{
  va_list args;
  uint32_t length;
 
  va_start(args, format);
  length = vsnprintf((char *)UserTxBufferFS, APP_TX_DATA_SIZE, (char *)format, args);
  va_end(args);
  CDC_Transmit_FS(UserTxBufferFS, length);
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */

将这个在.h文件声明:

/* USER CODE BEGIN EXPORTED_FUNCTIONS */
   void usb_printf(const char *format, ...);// printf
/* USER CODE END EXPORTED_FUNCTIONS */

在main中测试:

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
  HAL_Delay(1000);
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_I2C1_Init();
  MX_TIM2_Init();
  /* USER CODE BEGIN 2 */


  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  uint8_t UserTxBuffer[] = "STM32 Virtual COM Port Driver \r\n大家好\r\n";
  while (1)
  {

    usb_printf("%s \r\n",UserTxBuffer);
    HAL_Delay(1000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

下载,查看效果: