使用STM32CubeMX把USB配置成虚拟串口(virtual com port)

本文介绍了如何使用STM32CubeMX将STM32的USB配置为虚拟串口,以实现与老旧上位机的串口通信。通过详细步骤展示了从新建工程、配置时钟、USB功能选择到生成代码的全过程,并在测试中成功实现了数据的双向传输。

应用场景:

本次在项目中,由于对方的上位机软件比较老旧。
该软件只能通过串口通讯。而我们的设备只引出了USB口。还好STM32 的USB类型可以设置成虚拟串口。所以可以通过把USB枚举成虚拟串口(virtual com port设备)来与该上位机软件通讯。
本来是想直接移植STM32 的USB_FS库。奈何移植失败。(给跪了orz orz orz…)
又想起CubeMX也可以配置的。就用CubeMX配置工程,效果出奇的好。PC能够正常的枚举和通讯。所以趁热和大家分享分享,自己也做个记录。
以下内容就是如何一步一步通过CubeMX,把STM32的USB配置成虚拟串口的过程。
文章最后放上了本次CubeMX的工程和对应的虚拟串口代码。

配置过程:

1、点开CubeMX,新建工程,选择MCU。我用的是STM32F103VCT6。你们根据自己实际的MCU选择对应的型号以及封装格式。
在这里插入图片描述
在这里插入图片描述
2、选择系统时钟源。这边必须要配置,没配置系统时钟,不能生成正确的代码。
这里我使用的是外部晶振。(根据实际配置)
在这里插入图片描述
3、配置USB的上拉PIN脚。我这边的上拉PIN是PA13(根据实际情况配置)。注意硬件上DP要接个1.5K的上拉。用以表示高速设备以及枚举控制。
在这里插入图片描述
4、选上USB FS功能
在这里插入图片描述
5、继续“去中间层”,设置USB的识别类型。我们是虚拟口,所以选VCP设备。
在这里插入图片描述
6、配置系统时钟树参数。我的外部晶振是12M,所以要得到72M时钟,要选择倍频系数为6倍频。(晶振是8M则选择9倍频)
注意USB时钟要为48M。所以选1.5分频。
在这里插入图片描述
7、配置结束,去设置工程保存的位置。注意工具和版本。
在这里插入图片描述
8、生成工程。
在这里插入图片描述
在这里插入图片描述
9、打开工程,已经直接生成好了USB虚拟串口的代码。并可以直接编译不报错。
在这里插入图片描述

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 */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

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

10、这个时候载入生成的文件到MCU里,是不枚举的。因为自动生成的代码里,只完成初始化等一些基本功能。
在这里插入图片描述

PA13上拉以及收、发函数还需要我们自己完善才可以。

11、加入PA13上拉。编译载入,可以看到枚举出了com12虚拟口。

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_13, GPIO_PIN_SET);

在这里插入图片描述
12、调用发送函数。发送使用的是CDC_Transmit_FS函数。
所以我们在系统运行时,直接扔出个信息查看。编译并运行。发现确实有扔出信息(USB SYSTEM ON)。
在这里插入图片描述
13、调用接收函数CDC_Receive_FS。在CDC_Receive_FS里,把收到的数据进行计数以及保存。

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
	if(*Len<0x100)
	{
		uint16_t i;
		receive_len = *Len;
		for(i=0;i<*Len;i++)
			receivebuf[i] = Buf[i];
	}
	
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

14、做好了接收,我们在main里判断,接收的数据非空,则直接输出收到的数据。到此工程结束。

int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t i;
	
  /* 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 */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  /* USER CODE BEGIN 2 */
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_13, GPIO_PIN_SET);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
	for(i = 0;i < 5;i++)
	{
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
		delay_1000ms();
		HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
		delay_1000ms();
	}

	CDC_Transmit_FS("USB SYSTEM ON\r\n",15);
	
  while (1)
  {
		if(receive_len!=0)
		{
			CDC_Transmit_FS(receivebuf,receive_len);
			receive_len = 0;
			memset(receivebuf,0,sizeof(receivebuf));
		}

		
    /* USER CODE END WHILE */

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

运行测试:

PC往STM32 USB虚拟口输入什么,则STM32通过USB返回刚刚收到的内容。试验成功。
在这里插入图片描述

小结:

CubeMX确实是个挺好的工具。给大家提供了更多更简单的使用选项。

工程及源码:

CubeMX和程序源码链接: link.

### STM32CubeMX配置USB虚拟串口在Windows 11上的实现 在Windows 11系统中使用STM32CubeMX配置USB虚拟串口功能,首先需要确保开发环境的完整性,包括安装STM32CubeMX工具以及相关的HAL库和中间件支持。通过STM32CubeMXUSB CDC(Communication Device Class)驱动程序,可以实现基于USB接口的虚拟串口通信功能。该功能使得STM32微控制器可以通过USB接口模拟串口设备,从而与PC端进行数据交换。 在配置过程中,需要在STM32CubeMX中选择目标微控制器型号,并启用USB模块。接着,在“Middleware”选项中选择“USB Device”并设置为“CDC”模式。完基本配置后,生初始化代码,并将其导入到开发环境中(如STM32CubeIDE)。生的代码将包含USB驱动程序的基本框架,开发者可以根据具体需求进行扩展和优化。 在Windows 11系统中使用虚拟串口时,可能需要安装相应的驱动程序以确保操作系统能够正确识别设备。通常情况下,Windows系统自带的USB CDC驱动程序即可支持该功能,但为了确保兼容性和稳定性,建议使用STM32官方提供的驱动程序或通过设备管理器手动更新驱动。 此外,在实现USB虚拟串口功能时,需要注意波特率的配置问题。根据相关资料,当数据通讯到STM32内部设定的缓存空间而不向外部进行UART转发时,VCOM的波特率为名义上的波特率,实际上按照USB接口自动协商的差分速率进行数据传输。而在向外部进行UART转发时,UART的波特率可以单独配置,并不需要和VCOM配置的名义上的波特率相同。因此,在设计USB转TTL串口工具时,应确保USB传递的VCOM波特率信息用于配置转发的UART的波特率,并通过中断、DMA和缓存方式的配合,实现有效的时序转发[^2]。 对于调试和测试USB虚拟串口功能,可以借助虚拟串口工具如VSPD(Virtual Serial Port Driver)。该工具能够在Windows系统中创建虚拟串口对,使得开发者可以在没有实物的情况下随意调试串口功能。通过创建COM端口对(如COM3和COM4),可以模拟串口通信场景,从而验证USB虚拟串口的功能和性能[^3]。 ### 示例代码 以下是一个简单的示例代码,展示了如何在STM32CubeMX的代码基础上,实现USB CDC虚拟串口的基本功能: ```c #include "main.h" #include "usb_device.h" #include "usbd_cdc_if.h" // 定义接收缓冲区 uint8_t rx_buffer[64]; uint8_t tx_buffer[64]; // 接收数据处理函数 void process_data(uint8_t *data, uint16_t length) { // 将接收到的数据原样返回 CDC_Transmit_FS(data, length); } // 主函数 int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USB_DEVICE_Init(); // 无限循环 while (1) { // 检查是否有数据接收到 if (CDC_IsDataAvailable()) { // 读取接收到的数据 int len = CDC_ReadData(rx_buffer, sizeof(rx_buffer)); // 处理数据 process_data(rx_buffer, len); } } } ``` 上述代码中,`CDC_Transmit_FS`函数用于发送数据到主机,`CDC_ReadData`函数用于读取从主机接收到的数据。通过这种方式,可以实现基本的USB虚拟串口通信功能。 ### 相关问题 1. 如何在STM32CubeMX配置USB CDC类设备? 2. 如何在Windows 11系统中安装和配置USB CDC驱动程序? 3. 如何使用VSPD工具创建虚拟串口对并进行通信测试? 4. 如何在STM32上实现USB虚拟串口的数据接收和发送功能? 5. 在STM32上实现USB转UART功能时,如何配置波特率以确保通信的正确性?
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值