2020-03-26 07:55 AM
Hello,
There is an example to use printf with usart. However, I need to find a way to use scanf with usart. I am using STM32H7, STM32Cubemx, and Atollic Truestudio.
Your help is much appreciated.
2020-03-26 08:50 AM
Hi @VYoun ,
I know there is this exemple on MP1 Firmware package :
STM32Cube_FW_MP1_V1.2.0\Projects\STM32MP157C-DK2\Examples\UART\UART_Receive_Transmit_Console
Don't know if it has been ported to over MCU but might be fast forward to adapt to H7.
Hope it help,
Olivier
2020-03-26 08:56 AM
Hello @Community member
thank you very much for your answer, I will check right now.
Best regards,
Vouria
2020-03-26 09:07 AM
See
STM32Cube_FW_H7_V1.7.0\Projects\STM32H743I-EVAL\Examples\BSP\SW4STM32\syscalls.c
Implementation of plumbing using __io_putchar() __io_getchar() which would support putchar(), getchar(), scanf(), etc
You'd need to a) initialize the UART you plan on using and b) implement the __io_put/getchar functions
In a general GNU/GCC sense the functionality comes out of the _write() / _read() implementation you provide
2020-03-26 09:10 AM
Thank you very much for your answer Clive,
I will check right now.
Best regards,
Vouria
2020-03-26 09:53 AM
Keep in mind, that there is no stream buffering in the hardware or HAL driver, execpt you implement it.
When scanf is implemented straightforward using _read, you must always call scanf *before* there is any input on the RX line or you will get overrun errors.
2020-03-26 11:22 PM
... and don't forget to remove the stdio internal buffering. A plain call
int i;
scanf("%d",i);
ends up a in call to _read with a 1024 (BUFSIZ) char buffer! I.e. _read won't return before the UART supplied 1024 chars of input. This is not what you typically want for an interactive comm. You may remove that buffering by using
setvbuf( stdin, NULL, _IONBF, 0 );
scanf("%d",i);
which results in calls to _read single char by single char.
Anyway, I would prefer collecting a string manually using USART functions and then using sscanf on it.
2020-03-27 01:54 AM
Hello @KnarfB ,
Thank you very much for your reply. I tried the code that you provided but unfortunately I got no results.
I am coming to believe that it is not possible to use scanf with usart. I think I should use usart interrupt and then parse the received string. I am really lost in using scanf with usart.
2020-03-27 02:00 AM
Thank you again Clive, I checked the syscalls.c with my own syscals.c and the __io_putchar() __io_getchar() have the same implementation.
Below is my __io_getchar() implementation
int __io_getchar(void)
{
uint8_t ch = 0;
// Clear the Overrun flag just before receiving the first character
__HAL_UART_CLEAR_OREFLAG(&huart3);
HAL_UART_Receive(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
//HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
Do you suggest a different implementation of __io_getchar()?
Thank you in advance
2020-03-27 02:10 AM
Thank you again Olivier,
I tried the example and used the code below from the example
#ifdef __GNUC__
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif //__GNUC__
#ifdef __GNUC__
#define GETCHAR_PROTOTYPE int __io_getchar (void)
#else
#define GETCHAR_PROTOTYPE int fgetc(FILE * f)
#endif /* __GNUC__ */
GETCHAR_PROTOTYPE
{
uint8_t ch = 0;
// Clear the Overrun flag just before receiving the first character
__HAL_UART_CLEAR_OREFLAG(&huart3);
HAL_UART_Receive(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
HAL_UART_Transmit(&huart3, (uint8_t *)&ch, 1, 0xFFFF);
return ch;
}
However, the example uses a special type of scanf which is implemented in the code. This scanf function is implemented in the code and has the following implementation:
int Serial_Scanf(char *ptr, int len)
{
int DataIdx = 0;
uint8_t thechar;
thechar= ' ';
while(thechar!= '\n' && thechar != '\r' && DataIdx<len)
{
#ifdef __GNUC__
thechar = __io_getchar();
#else
thechar = fgetc(NULL);
#endif
if ( thechar >= 0xFF)
{
printf("\n\r !!! Please enter a valid ASCII character \n");
return 0xFF;
}
*ptr++ =thechar;
DataIdx+=1;
}
return DataIdx;
}
The problem with this scanf function is that the input length must be known. In my application this is not always known. However, I will try to utilize the above scanf function. I am happy to hear any suggestions. Thank you again for your help.
Best regards,
Vouria