全球最实用的IT互联网信息网站!

AI人工智能P2P分享&下载搜索网页发布信息网站地图

当前位置:诺佳网 > 电子/半导体 > 接口/总线/驱动 >

如何使用stm32 USB功能完成USB转串口功能

时间:2023-04-04 11:31

人气:

作者:admin

标签: USB  虚拟串口  STM32 

导读:如何使用stm32 USB功能完成USB转串口功能-设置系统时钟为72MHZ,调试串口UASART1波特率为921600(选择高波特率,少占用中断时间),USART2波特率默认为115200,开启中断。...

1. 开发环境

使用stm32f103c8t6,HAL库,使用CUBE自带的USB库。工程使用vscode+gcc编译,工程文件在文末链接下载,提供makefile和keil两个版本。

2. 功能介绍

使用stm32 USB功能完成USB转串口功能,使用引脚配置如下:

9d42da36-d298-11ed-bfe3-dac502259ad0.png

使用USART1作为调试信息输出,USART2作为串口输出,LED为系统指示。

3. CubeMX 配置

设置系统时钟为72MHZ,调试串口UASART1波特率为921600(选择高波特率,少占用中断时间),USART2波特率默认为115200,开启中断。

9d56cc9e-d298-11ed-bfe3-dac502259ad0.png

选择USB Device功能,速度为默认全速USB设备12MHZ,并使能USB_DEVICE库,选择Virtual Port Com (虚拟串口,VPC),使用默认配置。

9d687868-d298-11ed-bfe3-dac502259ad0.png

 

9d78650c-d298-11ed-bfe3-dac502259ad0.png

设置系统时钟为72MHZ,然后生成工程。

9d820422-d298-11ed-bfe3-dac502259ad0.png

4.软件部分

使用cube生成的代码编译下载后,将USB插入电脑,在电脑设备管理器中将显示新的串口设备(使用STM32的USB VPC时需要对应的驱动程序,驱动在程序也在文末的链接中)

9d92d572-d298-11ed-bfe3-dac502259ad0.png

在串口调试助手中,可打开或关闭串口,不过此时还没有任何功能。

4.1 发送函数

接下来进行功能配置,虚拟串口的主要配置代码在 src->usbd_cdc_if.c中,其中几个重要函数为:

 

 

static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length);
static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len);
uint8_t CDC_Control_FS(uint8_t* Buf, uint16_t Len);

 

 

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len);函数用于向USB VPC发送数据,Buf为待发送的数据缓冲区地址,Len为待发送数据长度。

 

 

/*示例一,在main函数中的while循环中输入下列代码
        在连接打开串口助手后可接收到数据*/
while(1)
{
    CDC_Control_FS((uint8_t *)"hello
",6);
    HAL_Delay(1000);
}

 

 

在编译下载后,将USB插入电脑,使用川酷哦调试助手将会每秒接收到一次"hello"。

4.2 USB上电重新枚举

在使用上面代码的时候存在一个问题:每次下载完程序后都需要重新拔插一次USB才可以识别串口,这是由于芯片在下载完程序后没有重新枚举所导致的。需要在设备上电后对USB进行重新枚举即可,使用方法为将USB DP(PA12)引脚拉低一段时间后即可。

 

 

/*USB 重新枚举函数*/
void USB_Reset(void)
{
      GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_GPIOA_CLK_ENABLE();
    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);
    HAL_GPIO_WritePin(GPIOA,GPIO_PIN_12,GPIO_PIN_SET);
}

 

 

该函数使用时应放在USB初始化之前,或者使用其他IO控制三极管拉低电平。

 

 

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

  /* USER CODE BEGIN SysInit */
  USB_Reset();
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USB_DEVICE_Init();
  MX_USART2_UART_Init();

9da064da-d298-11ed-bfe3-dac502259ad0.png

 

 

重新下载上电后,可发现串口已重新枚举识别,只需重新开启串口调试助手即可。

4.3 USB接收函数

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)为USB接收回调函数,在USB VPC接收到数据时,会进入该函数,在该函数中进行USB数据接收处理即可。

USB转串口设备,需要在stm32的USB端接收到数据后转发到stm32 串口端

 

 

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  extern UART_HandleTypeDef huart2,huart1;
  /*将USB接收到的数据转发到USART2*/
  HAL_UART_Transmit_IT(&huart2,Buf,*Len);
  
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  return (USBD_OK);
  /* USER CODE END 6 */
}

 

 

在stm32虚拟的串口中发送数据,可在stm32的USART2的TX引脚(PA2)收接收到数据。

9dabec24-d298-11ed-bfe3-dac502259ad0.png

4.4 设置USB虚拟串口波特率

在前面的发送和接收中,均不能进行波特率设置,usb发送到串口的数据波特率为默认值115200。USB的波特率配置在static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)函数中,cmd为usb cdc的控制命令,pbuf为数据接收指针,length为数据长度。

当cmd为0x20时为设置虚拟串口波特率;

9dc34fe0-d298-11ed-bfe3-dac502259ad0.png

其接收到的数据一共七位,数据格式定义(小端模式)如下:

9dd1d894-d298-11ed-bfe3-dac502259ad0.png

由于stm32芯片并不支持这么多串口参数,在无对应参数时使用默认配置。在接收到修改波特率命令后修改USART配置。

 

 

case CDC_SET_LINE_CODING:
{
      extern UART_HandleTypeDef huart2;
      huart2.Init.BaudRate=*((uint32_t*)pbuf);
      switch (pbuf[4])
      {
      case 2:
        huart2.Init.StopBits=UART_STOPBITS_2;
        break;
      default:
        huart2.Init.StopBits=UART_STOPBITS_1;
        break;
      }
      switch (pbuf[5])
      {
      case 1:
        huart2.Init.Parity=UART_PARITY_ODD;
        break;
      case 2:
        huart2.Init.Parity=UART_PARITY_EVEN;
        break;
      default:
        huart2.Init.Parity=UART_PARITY_NONE;
        break;
      }

      huart2.Init.WordLength=UART_WORDLENGTH_8B;
      HAL_UART_Init(&huart2);
}
break;

 

 

配置完成后,在串口调试助手中修改波特率,可该改变对应串口数据输出波特率,实测1.5M波特率可正常运行。

9ddcf13e-d298-11ed-bfe3-dac502259ad0.png

4.5 串口接收数据

在前面部分已经完成了USB转串口的发送部分,还有USB转串口的接收部分未完成。

该部分实现思路为在串口中断中接收数据,然后将数据发送至USB。

不过由于USB协议并不是实时发送,经过测试两次连续调用CDC_Transmit_FS小于100us将导致数据丢包,.并且由于USB缓冲区大小原因,一次性发送或接收大量数据将会严重丢包。

故使用循环队列对发送接收数据进行缓冲,在发送和接收数据时先进入缓冲区,然后使用定每隔500us定时将缓冲区数据分包发送。

编辑:黄飞

 

温馨提示:以上内容整理于网络,仅供参考,如果对您有帮助,留下您的阅读感言吧!
相关阅读
本类排行
相关标签
本类推荐

CPU | 内存 | 硬盘 | 显卡 | 显示器 | 主板 | 电源 | 键鼠 | 网站地图

Copyright © 2025-2035 诺佳网 版权所有 备案号:赣ICP备2025066733号
本站资料均来源互联网收集整理,作品版权归作者所有,如果侵犯了您的版权,请跟我们联系。

关注微信