完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一、前言
原来STM32USB开发很复杂,在标准库上移植USB库需要修改不少地方,但是现在用HAL库,配合CubeMX就能快速生成USB工程了,这里用STM32F1来实现Virtual_COM_Port虚拟串口。原理图如下,STM32F1的USB是USB2.0全速总线,所以DP上拉,DM不接上拉。 二、CubeMX配置 (1)mcu使用STM32F103C8 (2)RCC里高速和低速时钟都选择外部晶振Crystal 时钟树设置如下 (3)SYS调试口根据需要选择,这里选Serial Wire (4)Connectivity-USB勾线Device(FS),端口默认PA12(USB_DP),PA11(USB_DM) (5)Middleware-USB-DEVICE里Class For FS IP选择Communication Device Class(Virtual Port Com) (6)Project Manager填一下工程名和路径,堆栈改大一点,因为有人说堆栈小了会出问题,不过我试了一下其实不改也能用。IDE根据需要选择,这里用Keil所以选MDK-ARM V5 (7)代码生成里勾选复制所有库到工程,外设初始化单独.c/.h文件,方便以后工程拷贝,最后点生成GENERATE CODE (8)生成后打开工程,编译器改成 compiler version 6,这样编译速度能快几个世纪 (9)编译没错误后,下载到板子上,插上USB还无法识别,接下来就要安装STM32USB虚拟串口驱动 驱动已经打包上传,但是驱动安装有可能失败,博主就遇到了,可以根据以下办法解决 虚拟串口驱动安装失败解决办法: 将mdmcpq.inf复制到c:windowsinf 将u***ser.sys复制到c:windowssystem32drivers (10)驱动安装成功后,再插上USB,如果设备管理器端口里有Virtual COM Port,说明识别成功了,工程模板就算配置好了。 三、程序编写 现在只是识别串口,但是还没有功能,下面就来编写一下简单的功能 虚拟串口主要用到u***d_cdc_if.c里的两个缓存数组和收发函数。 uint8_t UserRxBufferFS[APP_RX_DATA_SIZE];//接收缓存 uint8_t UserTxBufferFS[APP_TX_DATA_SIZE];//发送缓存 static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)//接收回调函数 uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)//发送函数 CDC_Transmit_FS是发送函数,指定数据首地址和字节长度,数据就会发送到串口,底层是USB库实现的。 CDC_Receive_FS是接收到收据后的回调函数,数据是收到一帧后才调用的CDC_Receive_FS,所以每次的字节长度不一定相同,传入的两个参数是数据缓存首地址和数据长度。 (1)数据回环 这里简单的将接收到的数据原样返回,实现数据回环,只需要在CDC_Receive_FS函数添加一行: static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ CDC_Transmit_FS(Buf,*Len);//添加数据原样返回 USBD_CDC_SetRxBuffer(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } 下载到开发板,发送一定字节的数据会原样收到,注意注意发送字节长度不要超过缓存数组的最大长度1000,因为是虚拟的串口,所以波特率、停止位等其实可以随意设置, (2)指令控制 前面说了CDC_Receive_FS是接收回调函数,可以把它当作一个串口空闲中断 定义一个结构体变量 typedef struct { volatile uint8_t RecFlag; volatile uint16_t RecLen; }RxDef; extern RxDef USB_COM; 在u***d_cdc_if.c里接收到数据后标志置1,记录数据长度 static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ USB_COM.RecLen = *Len;//数据长度 USB_COM.RecFlag = 1;//收到标志 USBD_CDC_SetRxBuffer(&hU***DeviceFS, &Buf[0]); USBD_CDC_ReceivePacket(&hU***DeviceFS); return (USBD_OK); /* USER CODE END 6 */ } 主函数while循环里,处理接收到的指令数据 收到指令01 08 00 01开灯,并返回02 08 00 01 收到 01 08 00 00关灯,返回02 08 00 00 if(USB_COM.RecFlag)//接收到数据 { //4字节指令接收正确 if(USB_COM.RecLen==4 && UserRxBufferFS[0]==0x01 && UserRxBufferFS[1]==0x08 && UserRxBufferFS[2]==0x00) { if(UserRxBufferFS[3]) { UserTxBufferFS[3]=UserRxBufferFS[3]; LED_ON;//开灯 } else { UserTxBufferFS[3]=UserRxBufferFS[3]; LED_OFF;//关灯 } CDC_Transmit_FS(UserTxBufferFS,4);//返回指令 USB_COM.RecFlag = 0; } } 四、下载 例子下载 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
902 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
735 浏览 1 评论
427 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
338 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
772 浏览 2 评论
1486浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
161浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
199浏览 3评论
172浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
175浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-7-9 06:09 , Processed in 0.724639 second(s), Total 76, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191