> 技术文档 > STM32 USB CDC 连续发送

STM32 USB CDC 连续发送


一、问题

在用STM32CUBEMX生成的USB_DEVICE项目过程中发现连续发送时总是会返回USBD_BUSY状态码,在此记录一下。

while(1){ HAL_Delay(100); CDC_Transmit_FS(\"USBD CDC\\r\\n\",strlen(\"USBD CDC\\r\\n\"); CDC_Transmit_FS(\"USBD TEST\\r\\n\",strlen(\"USBD TEST\\r\\n\");}

在执行如上函数时,总是会只打印\"USBD CDC\\r\\n\",而\"USBD TEST\\r\\n\"则不会打印,在DEBUG调试中是正常的。

二、查阅发现

USB是轮询机制,主机对设备不断轮询,间隔最小1ms;不是固定的1ms,  是最小间隔时间;
USB的数据,是按包传输的; 
每个设备,每1ms,最多传输1包数据;
每包最多64字节(有效负载);
再说说,CDC_Transmit_FS ( ) 函数:

它的第2个参数,\"字节数\",范围:0~2048; 这个2048可以在CubeMX里进行设置大小; 
字节数 <= 64,算1包。如:发3个字节,也算1包。
字节数 == 0,也算1包。俗称:空包; 如果上一帧刚好发送64字节,再发一个空包作为结束包;
字节数 > 64, CDC_Transmit_FS ( ) 背后有缓存,它自动分包,1ms左右发1包,直至发完;
如果上一包还没发完,再次调用CDC_Transmit_FS ( ) ,将放弃本次调用。
上面while循环中,连续、两次调用CDC_Transmit_FS ( ) .第1次调用,将正常发出一包数据;
第2次调用,再发送一包。但是,两包没有间隔1ms以上,导致了第2次的发送,被舍弃了。
                        
原文链接:https://blog.csdn.net/qq_49053936/article/details/142363059

大佬写得很好很详细,留存学习。

三、解决方法

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; uint32_t timeout = HAL_GetTick(); while (hcdc->TxState != 0){ if (HAL_GetTick() - timeout > 10) return USBD_BUSY; } USBD_CDC_SetTxBuffer(&hUsbDeviceFS, Buf, Len); result = USBD_CDC_TransmitPacket(&hUsbDeviceFS); /* USER CODE END 7 */ return result;}

增加等待发送空闲、超时判断机制,优化连续发送。