Reputation: 424
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?
Upvotes: 0
Views: 2095
Reputation: 78795
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, i.e. 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:
line_buffer
.'\r'
and '\n'
character as a line separator. So you might want to remove the '\r'
character.void*
to char*
or from uint32_t
to int
.Upvotes: 3