繁体   English   中英

STM32 USB CDC 长包接收

[英]STM32 USB CDC Long packet receive

我需要将数据从 PC 发送到我的 STM32F3,所以我决定在 uC 中使用内置 USB。 但现在我有一个问题——我想一次向 stm32 发送大量数据——我的意思是 200-500 字节。

当我从 PC 发送带有少于 64 个图表的 minicom 数据包时 - 一切都很好 - 回调 CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) 发生一次 - 它启用 UsbRxFlag,只是为了通知正在运行的程序有可用的数据。

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);
  if( (Buf[0] == 'A') & (Buf[1] == 'T') ){
      GPIOB->BSRR = (uint32_t)RX_Led_Pin;
      UsbRxFlag = 1;
  }

  return (USBD_OK);
  /* USER CODE END 6 */
}

但是当我尝试向 uC 发送更多数据(只是来自 minicom 的长文本)时,会发生一些奇怪的事情——有时 uC 根本没有反应——有时它没有考虑到一些数据。

如何处理通过 USB-CDC 向 STM32F3 发送超过 64 字节的数据?

全速 USB 通信的最大数据包长度为 64 字节。 因此数据将以 64 字节的块传输,并且需要在另一端重新组合。

USB CDC 基于批量传输端点并实现数据流(也称为管道),而不是消息流。 它基本上是一个字节流。 因此,如果您发送 200 个字节,不要指望 200 个字节在哪里结束。 不传输此类信息。

您的代码看起来有点可疑:

  • 正如Reinstate Monica指出的那样,您可能指的是 '&&' 而不是 '&' 。
  • 除非您更改缓冲区,否则USBD_CDC_SetRxBuffer只需要在初始化时调用一次。
  • CDC_Receive_FS时,已经接收到一个数据包。 Buf将指向您使用USBD_CDC_SetRxBuffer指定的缓冲区。 Len提供数据包的长度。 所以你要做的第一件事就是处理接收到的数据。 处理完数据并且可以再次重用缓冲区后,您将调用USBD_CDC_ReceivePacket以指示您已准备好接收下一个数据包。 因此,将USBD_CDC_SetRxBuffer移动到另一个函数(除非您想使用多个缓冲区)并将 USBD_CDC_ReceivePacket 移动到USBD_CDC_ReceivePacketCDC_Receive_FS

函数调用的错误顺序可能会导致接收到的数据在您仍在处理时被覆盖。

但最大的问题可能是,如果您发送的是单件,或者它至少包含一段结束的指示,那么您可能期望整个数据是在单件中接收的。 事实并非如此。 您必须自己实施。

如果您使用的是文本协议,则可以缓冲所有传入数据,直到检测到换行为止。 然后你知道你有一个完整的命令并且可以执行它。

以下是用于读取任意数量字节的通用实现: https ://github.com/philrawlings/bluepill-usb-cdc-test。

完整的代码有点太长,无法在此处发布,但这实质上修改了usb_cdc_if.c以创建循环缓冲区并公开其他函数( CDC_GetRxBufferBytesAvailable_FS()CDC_ReadRxBuffer_FS()CDC_FlushRxBuffer_FS() ),这些函数可以从main.c使用。 主页上显示的 readme.md 文本描述了所需的所有代码更改。

正如@Codo 所提到的,您需要在源数据中添加终止字符,或者在开头包含一个“长度”值(它本身是一个固定的字节数),然后指示数据中有多少字节有效载荷。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM