Skip to main content
Associate II
August 28, 2024
Solved

scanf() can only read one character

I am trying to use scanf() in STM32H743, referring a webpage (here). More specifically, after setting up USART1 in STM32CubeMX, I add some function prototypes like:

 

 

 

#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#define GETCHAR_PROTOTYPE int __io_getchar(void)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#define GETCHAR_PROTOTYPE int fgetc(FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
 HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
 return ch;
}

GETCHAR_PROTOTYPE
{
 uint8_t ch = 0;

 /* Clear the Overrun flag just before receiving the first character */
 __HAL_UART_CLEAR_OREFLAG(&huart1);

 /* Wait for reception of a character on the USART RX line and echo this
 * character on console */
 HAL_UART_Receive(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
 // HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, HAL_MAX_DELAY);
 return ch;
}

 

 

 

and add a scanf() in the main function before infinite while loop:

 

 

 

scanf("%c", &c);

 

 

 

where c is a char.

I found that if I read one character (e.g. a char variable) every time, the function works well. But if I try to read more like integers and strings, the function seems being stuck. I don't know where it is stuck and why it happened. Please help. Any help is appreciated.

 

EDIT: I have added "setvbuf(stdin, NULL, _IONBF, 0);" before any scanf() call.

This topic has been closed for replies.
LittleYe233Best answer
Associate II
August 28, 2024

@Peter BENSCH @SMarie @Andrew Neil Thanks for your fast replies. I forget to mention in the first thread that I actually added "setvbuf()" before any scanf() call. And I found that this situation happened because I forgot to automatically add LF after my input in the serial termial. With LF or CR/LF, scanf() begins to work well again. That's all my fault and thank you all again.

5 replies

Peter BENSCH
ST Technical Moderator
August 28, 2024

Try deactivating the buffering before scanf():

setvbuf(stdin, NULL, _IONBF, 0);

Regards
/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Associate II
August 28, 2024

Did you add the config indicated in the link you gave ?

setvbuf(stdin, NULL, _IONBF, 0);

If not could you try it ?
If you did, could you show us the rest of your code ?

S. Marie

Andrew Neil
Super User
August 28, 2024

@LittleYe233 wrote:

But if I try to read more like integers and strings, the function seems being stuck.


How, exactly, are you testing that?

@Peter BENSCH and @SMarie have suggested disabling buffering - so does your input work as-is if you terminate entry with CR and/or LF ?

 

EDIT:

See this thread on the buffering of stdin, etc:

https://community.st.com/t5/stm32-mcus-products/stm32g030-usart-and-hal-delay-strange-behavior/m-p/640684

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
LittleYe233AuthorBest answer
Associate II
August 28, 2024

@Peter BENSCH @SMarie @Andrew Neil Thanks for your fast replies. I forget to mention in the first thread that I actually added "setvbuf()" before any scanf() call. And I found that this situation happened because I forgot to automatically add LF after my input in the serial termial. With LF or CR/LF, scanf() begins to work well again. That's all my fault and thank you all again.

Andrew Neil
Super User
August 28, 2024

Good to hear - please mark the solution:

https://community.st.com/t5/community-guidelines/help-others-to-solve-their-issues/ta-p/575256

I think this is defined behaviour for stdin in the standard C library.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.