STM32 USB CDC 长包接收

Nik*_*iko 3 c usbserial cdc stm32

我需要将数据从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 */
}
Run Code Online (Sandbox Code Playgroud)

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

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

Cod*_*odo 7

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

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

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

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

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

但最大的问题可能是,如果您发送的是单个数据段,则您可能希望整个数据以单个数据段的形式接收,或者它至少包含该数据段结束的指示。事实并非如此。您必须自己实现这一点。

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

  • 批量端点实现数据流,而不是基于消息或数据包的协议。在发送端,数据包可以以发送者认为最佳的任何方式组合或拆分。事实上,Windows、Linux 和 macOS 都会合并数据,如果超过 64 字节,则必须将其拆分。例如,如果您短时间连续发送 10 次 10 个字节,则前 10 个字节可能会立即发送,而其余字节则被组合起来,然后分成 64 字节的块和 26 字节的另一个块。 (2认同)