现在STM32库是有个TXState用来表示是否发送完毕,比如:
hcdc->TxState=1;
USBD_LL_Transmit(...)
while(hcdc->TxState==0);
在USB的DataIN函数里,
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc;
PCD_HandleTypeDef *hpcd = pdev->pData;
if (pdev->pClassData == NULL)
{
return (uint8_t)USBD_FAIL;
}
hcdc = (USBD_CDC_HandleTypeDef *)pdev->pClassData;
if ((pdev->ep_in[epnum].total_length > 0U) &&
((pdev->ep_in[epnum].total_length % hpcd->IN_ep[epnum].maxpacket) == 0U))
{
/* Update the packet total length */
pdev->ep_in[epnum].total_length = 0U;
/* Send ZLP */
(void)USBD_LL_Transmit(pdev, epnum, NULL, 0U);
}
else
{
hcdc->TxState = 0U;
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);
}
return (uint8_t)USBD_OK;
}
可以看到为我们处理了整数倍发送需要在补0字节的一个包的特殊情况:
我这里使用了操作系统,也就是说一个信号量代替了TXState,然后在else
{
hcdc->TxState = 0U;
((USBD_CDC_ItfTypeDef *)pdev->pUserData)->TransmitCplt(hcdc->TxBuffer, &hcdc->TxLength, epnum);
}将hcdc->TxState = 0U;改成了xSemaphoreGiveFromISR(...)为的是不要死等。
然后单片机发送256字节,结果上位机只能收到一次或者收不到,
我研究了下库,最终我自己处理整数倍发送的问题,不用STM32官方库处理了。代码改成如下所示就好了:
static uint8_t USBD_CDC_DataIn(USBD_HandleTypeDef *pdev, uint8_t epnum)
{
USBD_CDC_HandleTypeDef *hcdc;
PCD_HandleTypeDef *hpcd = pdev->pData;
xSemaphoreGiveFromISR(....)
return (uint8_t)USBD_OK;
}
...
uint8_t CDC_Transmit_FS(uint8_t* Buf, uint32_t Len)
{
复位信号量;
发你的数据;
等待信号量;
if(Len%64==0)//注意 我实测,哪怕是高速USB,这里我之前以为应该是和512取余数,但实测不行 必须是64
{
复位信号量;
发0长度数据;
等待信号量;
}
/* USER CODE END 7 */
return result;
}