简体   繁体   中英

stm32 USB receive more than 1 byte

I am trying to establish a USB communication between PC and a STM32 MCU. I want to receive an integer from a PC. (range of the integer is between 0 and 20.000). I added those lines:

To usb_cdc_if.h :

_weak void CDC_ReceiveCallBack(uint8_t *buf, uint32_t len);

To the usb_cdc_if.c

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);
  CDC_ReceiveCallBack(Buf, Len);
  return (USBD_OK);
  /* USER CODE END 6 */
}
.
.
.
__weak void CDC_ReceiveCallBack(uint8_t *buf, uint32_t len)
{}

And in the main class:

void CDC_ReceiveCallBack(uint8_t *buf, uint32_t len)
{

fan_speed=atoi(buf);
    memset(statusString,0x00,255);
statusStringLength = sprintf(statusString,"Fan Speed: %d ", fan_speed);
    CDC_Transmit_FS(statusString,statusStringLength);
}

So I can only receive 1 digit numbers. Should I add an if statement to the beginning of function and when enter is pressed, then I should receive it from buffer?

I'm assuming that you are tyring to implement a serial connection (aka Virtual COM Port) over USB and that you have a terminal application connected to it on the PC...

If so, you need to understand that:

  • The characters sent from the PC to the MCU can be chopped up into arbitrary packets. It's not possible to ensure that a piece of text is in the same packet. If you are typing in a terminal program, it's even likely that each character is sent in a separate packet. If you paste a long text into the terminal program, it's likely that you receive long packets of up to 64 characters.

  • The received data is an array of characters. It's not a string (with a '\\0' termination). So string functions such as atoi or strlen must not be used unless the data has been converted to a string.

In order to progress:

  • Add code that detects when sufficient data has been received to process it. A typical approach is to use the linefeed character for it, ie you save all recieved data until a full line has been received. Then the entire line is processed.

  • In the saved data, add a '\\0' character. That way, the buffer becomes a string and can be processed with string functions.

It could look something like this:

char line_buffer[80];
int line_len = 0;

void CDC_ReceiveCallBack(uint8_t *buf, uint32_t len)
{
    // append received data to line buffer
    memcpy(line_buffer + line_len, buf, len);
    line_len += len;

    while (1) {
        // check for linefeed character
        char* line_feed = memchr(buf, '\n', line_len);
        if (line_feed == NULL)
            break;

        // add string termination
        *line_feed = '\0';
        process_line(line_buffer);

        // copy remaining data to start of line buffer
        line_len -= line_feed + 1 - line_buffer;
        memcpy(line_buffer, line_feed + 1, line_len);
    }
}

void process_line(char* line) {
    // do something with the line; string functions are ok
}

Note that the code is incomplete:

  • It does not check if the received data fits into line_buffer .
  • You will likely receive both a '\\r' and '\\n' character as a line separator. So you might want to remove the '\\r' character.
  • I haven't tested the code. It's likely missing some conversions from void* to char* or from uint32_t to int .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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