1
完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
扫一扫,分享给好友
STM32 USB系列之虚拟串口
这段时间缓慢更新一下stm32 u***系列的博客,前段时间在多个地方零零散散的学习和使用USB协议,在网上查找的资料也是零零散散的,整理一下写成博客。 1. 开发环境 使用stm32f103c8t6,HAL库,使用CUBE自带的USB库。工程使用vscode+gcc编译,工程文件在文末链接下载,提供makefile和keil两个版本。 2. 功能介绍 使用stm32 USB功能完成USB转串口功能,使用引脚配置如下: 使用USART1作为调试信息输出,USART2作为串口输出,LED为系统指示。 3. CubeMX 配置 设置系统时钟为72MHZ,调试串口UASART1波特率为921600(选择高波特率,少占用中断时间),USART2波特率默认为115200,开启中断。 选择USB Device功能,速度为默认全速USB设备12MHZ,并使能USB_DEVICE库,选择Virtual Port Com (虚拟串口,VPC),使用默认配置。 设置系统时钟为72MHZ,然后生成工程。 4.软件部分 使用cube生成的代码编译下载后,将USB插入电脑,在电脑设备管理器中将显示新的串口设备(使用STM32的USB VPC时需要对应的驱动程序,驱动在程序也在文末的链接中) 在串口调试助手中,可打开或关闭串口,不过此时还没有任何功能。 4.1 发送函数 接下来进行功能配置,虚拟串口的主要配置代码在 src->u***d_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 *)"hellon",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(); 重新下载上电后,可发现串口已重新枚举识别,只需重新开启串口调试助手即可。 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(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } 在stm32虚拟的串口中发送数据,可在stm32的USART2的TX引脚(PA2)收接收到数据。 4.4 设置USB虚拟串口波特率 在前面的发送和接收中,均不能进行波特率设置,u***发送到串口的数据波特率为默认值115200。 USB的波特率配置在static int8_t CDC_Control_FS(uint8_t cmd, uint8_t* pbuf, uint16_t length)函数中,cmd为u*** cdc的控制命令,pbuf为数据接收指针,length为数据长度。 当cmd为0x20时为设置虚拟串口波特率; 其接收到的数据一共七位,数据格式定义(小端模式)如下: [tr]偏移含义数据大小说明[/tr]
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波特率可正常运行。 4.5 串口接收数据 在前面部分已经完成了USB转串口的发送部分,还有USB转串口的接收部分未完成。 该部分实现思路为在串口中断中接收数据,然后将数据发送至USB。 不过由于USB协议并不是实时发送,经过测试两次连续调用CDC_Transmit_FS小于100us将导致数据丢包,.并且由于USB缓冲区大小原因,一次性发送或接收大量数据将会严重丢包。 故使用循环队列对发送接收数据进行缓冲,在发送和接收数据时先进入缓冲区,然后使用定每隔500us定时将缓冲区数据分包发送。 附件 如果感觉写的还不错的话,给我点个赞或者github来一个star吧! |
|||
|
|||
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1777 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1621 浏览 1 评论
1080 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
728 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1678 浏览 2 评论
1938浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
731浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
570浏览 3评论
595浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
554浏览 3评论
小黑屋| 手机版| Archiver| 德赢Vwin官网 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-23 04:54 , Processed in 0.654954 second(s), Total 46, Slave 40 queries .
Powered by 德赢Vwin官网 网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
德赢Vwin官网 观察
版权所有 © 湖南华秋数字科技有限公司
德赢Vwin官网 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号