简体   繁体   English

STM32 USB CDC 长包接收

[英]STM32 USB CDC Long packet receive

I need to send data from the PC to my STM32F3, so I decided to use a built-in USB in uC.我需要将数据从 PC 发送到我的 STM32F3,所以我决定在 uC 中使用内置 USB。 But now I have a problem - I want to send to stm32 big amount of data at once - I mean something like 200-500 Bytes.但现在我有一个问题——我想一次向 stm32 发送大量数据——我的意思是 200-500 字节。

When I send from PC with minicom packets which have less than 64 chart - everything is fine - callback CDC_Receive_FS(uint8_t* Buf, uint32_t *Len) occurs once - it enables UsbRxFlag, just to inform the running program that there is data available.当我从 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 */
}

But when I try to send more data (just long text from minicom ) to uC, something weird happens - sometimes uC doesn't react at all - sometimes it doesn't take into account some data.但是当我尝试向 uC 发送更多数据(只是来自 minicom 的长文本)时,会发生一些奇怪的事情——有时 uC 根本没有反应——有时它没有考虑到一些数据。

How can I handle sending to STM32F3 more than 64Bytes over USB-CDC?如何处理通过 USB-CDC 向 STM32F3 发送超过 64 字节的数据?

The maximum packet length for full-speed USB communication is 64 bytes.全速 USB 通信的最大数据包长度为 64 字节。 So the data will be transferred in chunks of 64 bytes and needs to be reassembled on the other end.因此数据将以 64 字节的块传输,并且需要在另一端重新组合。

USB CDC is based on bulk transfer endpoints and implements a data stream (also known as pipe ), not a message stream. USB CDC 基于批量传输端点并实现数据流(也称为管道),而不是消息流。 It's basically a stream of bytes.它基本上是一个字节流。 So if you send 200 bytes, do not expect any indication of where the 200 bytes end.因此,如果您发送 200 个字节,不要指望 200 个字节在哪里结束。 Such information is not transmitted.不传输此类信息。

Your code looks a bit suspicious:您的代码看起来有点可疑:

  • You probably meant '&&' instead of '&' as pointed out by Reinstate Monica .正如Reinstate Monica指出的那样,您可能指的是 '&&' 而不是 '&' 。
  • Unless you change buffers, USBD_CDC_SetRxBuffer only needs to be called once at initialization.除非您更改缓冲区,否则USBD_CDC_SetRxBuffer只需要在初始化时调用一次。
  • When CDC_Receive_FS is called, a data packet has already been received.CDC_Receive_FS时,已经接收到一个数据包。 Buf will point to the buffer you have specified with USBD_CDC_SetRxBuffer . Buf将指向您使用USBD_CDC_SetRxBuffer指定的缓冲区。 Len provides the length of the packet. Len提供数据包的长度。 So the first thing you would do is process the received data.所以你要做的第一件事就是处理接收到的数据。 Once the data has been processed and the buffer can be reused again, you would call USBD_CDC_ReceivePacket to indicate that you are ready to receive the next packet.处理完数据并且可以再次重用缓冲区后,您将调用USBD_CDC_ReceivePacket以指示您已准备好接收下一个数据包。 So move USBD_CDC_SetRxBuffer to another function (unless you want to use several buffers) and move USBD_CDC_ReceivePacket to the end of CDC_Receive_FS .因此,将USBD_CDC_SetRxBuffer移动到另一个函数(除非您想使用多个缓冲区)并将 USBD_CDC_ReceivePacket 移动到USBD_CDC_ReceivePacketCDC_Receive_FS

The incorrect order of the function calls could likely have led to the received data being overwritten while you are still processing it.函数调用的错误顺序可能会导致接收到的数据在您仍在处理时被覆盖。

But the biggest issue is likely that you expect that the entire data is received in a single piece if you sent is as a single piece, or that it at least contains an indication of the end of the piece.但最大的问题可能是,如果您发送的是单件,或者它至少包含一段结束的指示,那么您可能期望整个数据是在单件中接收的。 That's not the case.事实并非如此。 You will have to implement this yourself.您必须自己实施。

If you are using a text protocol, you could buffer all incoming data until you detect a line feed.如果您使用的是文本协议,则可以缓冲所有传入数据,直到检测到换行为止。 Then you know that you have a complete command and can execute it.然后你知道你有一个完整的命令并且可以执行它。

The following is a general purpose implementation for reading an arbitrary number of bytes: https://github.com/philrawlings/bluepill-usb-cdc-test .以下是用于读取任意数量字节的通用实现: https ://github.com/philrawlings/bluepill-usb-cdc-test。

The full code is a little too long to post here, but this essentially modifies usb_cdc_if.c to create a circular buffer and exposes additional functions ( CDC_GetRxBufferBytesAvailable_FS() , CDC_ReadRxBuffer_FS() and CDC_FlushRxBuffer_FS() ) which can be consumed from main.c .完整的代码有点太长,无法在此处发布,但这实质上修改了usb_cdc_if.c以创建循环缓冲区并公开其他函数( CDC_GetRxBufferBytesAvailable_FS()CDC_ReadRxBuffer_FS()CDC_FlushRxBuffer_FS() ),这些函数可以从main.c使用。 The readme.md text shown on the main page describes all the code changes required.主页上显示的 readme.md 文本描述了所需的所有代码更改。

As mentioned by @Codo, you will need to either add termination characters to your source data, or include a "length" value (which itself would be a fixed number of bytes) at the beginning to then indicate how many bytes are in the data payload.正如@Codo 所提到的,您需要在源数据中添加终止字符,或者在开头包含一个“长度”值(它本身是一个固定的字节数),然后指示数据中有多少字节有效载荷。

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

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