STM32F103C8T6的USB—CDC虚拟端口组件(HAL)

STM32F103C8T6的USB—CDC虚拟端口组件(HAL)
常见的STM32USB端口是Micro-USBType-C,USB-BT型口USB-B方口我们最常见的32最小系统板上的USBD和D-就接到了PA11和PA12单片机I/O端口上新一版的小篮板STM32F103C8T6用的是Type-C旧一版用的是Micro-USB需要准备对应的线。我们主要实现USB的虚拟串口的功能用CubeMX新建工程例程很多我只展示主要的部分1.Connectivity中下拉找到USB勾选Device(FS)设备全速模式,其他的保持默认在Middleware and Software Packs中间件和软件包中找到USB_DEVICE在 Class For FS IP 设备类别选择Communication Device ClassVirtual Port Com虚拟串口。其他设置保持默认就行。2.接下来进行时钟树配置这是自动配置时钟树选项可以选择Yes让它帮你配但是要注意配完后的时钟主频只有48有要求的可以自己改到72M。这是我的配置后面的步骤和CubeMX新建工程一样我就不说明了。3.打开project工程在这里我们要实现发什么回什么的类串口功能该功能主要用到usbd_cdc_if.c和usbd_cdc_if.h这两个文件。/** * brief Data received over USB OUT endpoint are sent over CDC interface * through this function. * * note * This function will issue a NAK packet on any OUT packet received on * USB endpoint until exiting this function. If you exit this function * before transfer is complete on CDC interface (ie. using DMA controller) * it will result in receiving more data while previous ones are still * not sent. * * param Buf: Buffer of data to be received * param Len: Number of data received (in bytes) * retval Result of the operation: USBD_OK if all operations are OK else USBD_FAIL */ static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) { /* USER CODE BEGIN 6 */ USBD_CDC_SetRxBuffer(hUsbDeviceFS, Buf[0]); //将接收到的数据存到缓冲区 USBD_CDC_ReceivePacket(hUsbDeviceFS); //准备主设备输出端口进行数据发送 return (USBD_OK); /* USER CODE END 6 */ } /** * brief CDC_Transmit_FS * Data to send over USB IN endpoint are sent over CDC interface * through this function. * note * * * param Buf: Buffer of data to be sent * param Len: Number of data to be sent (in bytes) * retval USBD_OK if all operations are OK else USBD_FAIL or USBD_BUSY */ uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) { uint8_t result USBD_OK; /* USER CODE BEGIN 7 */ USBD_CDC_HandleTypeDef *hcdc (USBD_CDC_HandleTypeDef*)hUsbDeviceFS.pClassData; //将USB当作类串口 if (hcdc-TxState ! 0){ //如果串口发送内容不为0 return USBD_BUSY; //返回忙碌 } USBD_CDC_SetTxBuffer(hUsbDeviceFS, Buf, Len); //发送内容 result USBD_CDC_TransmitPacket(hUsbDeviceFS); //将发送内容传给result /* USER CODE END 7 */ return result; }我们主要用到CDC_Receive_FS、CDC_Transmit_FS这两个函数我们先用发送函数编译后会出现函数隐式声明的警告这是因为在#include usb_device.h头文件中并没有包含#include usbd_cdc_if.h头文件所以我们要添加#include usbd_cdc_if.h头文件再次编译就不会报警告了。试验需要一根USB的线要与自己的STM32USB口适配、任意串口助手软件可以按照图示连接建议只先链接ST-LINK将程序下载到STM32里下载完成后断开ST-LINK只用USB链接打开设备管理器检查USB是否正常连接若没有则检查USB连接、STM32接口是否正常、电脑接口是否正常、USB驱动是否安装...打开串口助手我用的是微软商店自带的选择与之对应的COM端口和115200波特率可以看到成功接收到了信息。注意因为是CDC虚拟串口波特率、停止位等设置对 USB CDC 是无效的接下来我们改动回传函数达到发什么回什么的功能在CDC_Receive_FS函数中加上CDC_Transmit_FS(Buf,*Len);这一句注意 USBD_CDC_ReceivePacket(hUsbDeviceFS);这个函数告诉 USB 控制器“这包数据我处理完了请准备好接收下一包”如果漏掉这句单片机只能收到电脑发来的第 1 包数据之后就会“失联”所以CDC_Transmit_FS(Buf,*Len);这一句应该加在USBD_CDC_ReceivePacket前面。主函数什么都不写编译下载下载后拔掉ST-LINK接上USB打开串口助手可以看到成功发回了注意事项1.不要在 CDC_Receive_FS 回调里加 HAL_Delay()、while() 死循环或 Flash/EEPROM 操作该函数在中断上下文执行阻塞会导致 USB 枚举超时、电脑端串口卡死。2.漏写 USBD_CDC_ReceivePacket(hUsbDeviceFS); 只能收到电脑发来的第 1 包数据之后单片机“变聋”。3.直接操作 Buf 指针而不拷贝 Buf 指向的是 USB 底层临时缓冲区。下一次接收会直接覆盖它。如需保留数据必须 memcpy 到自定义数组。4.在 main.c 里直接调用 CDC_Receive_FS它是底层自动触发的回调手动调用会破坏 USB 状态机。5.在使用DMA时要考虑缓冲区匹配问题。链接: https://pan.baidu.com/s/1P-7RaN2Yy3CKXNVaj1LuuA?pwd6524 提取码: 6524