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;}
增加等待发送空闲、超时判断机制,优化连续发送。