STM32 printf and scanf function redirection

1. Method 1

///Redirect c library function printf to USART1
int fputc(int ch, FILE *f)
{
		/* Send a byte of data to USART1 */
		USART_SendData(USART1, (uint8_t) ch);
		
		/* Waiting to send */
		while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);		
	
		return (ch);
}

///Redirect c library function scanf to USART1
int fgetc(FILE *f)
{
		/* Wait for serial port 1 to input data */
		while (USART_GetFlagStatus(USART1, USART_FLAG_RXNE) == RESET);

		return (int)USART_ReceiveData(USART1);
}

2. Method 2 (only printf)

//Need to add this header file
#include "stdarg.h"

static char *    itoa         ( int value, char * string, int radix );

/*
 * Function name: usart2? Printf
 * Description: format output, similar to printf in C library, but C library is not used here
 * Input: - USARTx serial port channel, only serial port 2 is used here, i.e. USART2
 *		     -Data   Pointer to the content to be sent to the serial port
 *			   -...    Other parameters
 * Output: None
 * Return: None 
 * Calls: external calls
 *         Typical application usart2 ﹣ printf (usart2, "\ R \ n this is a demo \ R \ n");
 *            		 USART2_printf( USART2, "\r\n %d \r\n", i );
 *            		 USART2_printf( USART2, "\r\n %s \r\n", j );
// */
void USART2_printf ( USART_TypeDef * USARTx, char * Data, ... )
{
	const char *s;
	int d;   
	char buf[16];

	
	va_list ap;
	va_start(ap, Data);

	while ( * Data != 0 )     // Determine whether the string terminator is reached
	{				                          
		if ( * Data == 0x5c )  //'\'
		{									  
			switch ( *++Data )
			{
				case 'r':							          //Carriage return character
				USART_SendData(USARTx, 0x0d);
				Data ++;
				break;

				case 'n':							          //Newline character
				USART_SendData(USARTx, 0x0a);	
				Data ++;
				break;

				default:
				Data ++;
				break;
			}			 
		}
		
		else if ( * Data == '%')
		{									  //
			switch ( *++Data )
			{				
				case 's':										  //Character string
				s = va_arg(ap, const char *);
				
				for ( ; *s; s++) 
				{
					USART_SendData(USARTx,*s);
					while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
				}
				
				Data++;	
				break;
				case 'd':			
					//Decimal system
				d = va_arg(ap, int);		
				itoa(d, buf, 10);			
				for (s = buf; *s; s++) 
				{
					USART_SendData(USARTx,*s);
					while( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) == RESET );
				}				
				Data++;				
				break;				
				default:
				Data++;	
				break;	
			}		 
		}
		else USART_SendData(USARTx, *Data++);
		while ( USART_GetFlagStatus ( USARTx, USART_FLAG_TXE ) == RESET );	
	}
}



/*
 * Function name: itoa
 * Description: converts the shape data to a string
 * Input: - radix =10 for decimal, other results are 0
 *         -value Number of integers to convert
 *         -buf Converted String
 *         -radix = 10
 * Output: None
 * Return: None
 * Call: called by usart2 ﹐ printf()
 */
static char * itoa( int value, char *string, int radix )
{
	int     i, d;
	int     flag = 0;
	char    *ptr = string;

	/* This implementation only works for decimal numbers. */
	if (radix != 10)
	{
		*ptr = 0;
		return string;
	}

	if (!value)
	{
		*ptr++ = 0x30;
		*ptr = 0;
		return string;
	}

	/* if this is a negative value insert the minus sign. */
	if (value < 0)
	{
		*ptr++ = '-';

		/* Make the value positive. */
		value *= -1;
		
	}

	for (i = 10000; i > 0; i /= 10)
	{
		d = value / i;

		if (d || flag)
		{
			*ptr++ = (char)(d + 0x30);
			value -= (d * i);
			flag = 1;
		}
	}

	/* Null terminate the string. */
	*ptr = 0;

	return string;

} /* NCL_Itoa */

3. method three

#if 1
#pragma import(__use_no_semihosting_swi)
/*The support function required by the standard library, use? No? Semihosting? SWI to avoid the use of semi host mode*/

struct __FILE
{
	int handle;
};

FILE __stdout;
FILE __stdin;
/*Redirect Printf function*/

int fputc(int ch,FILE *f)
{
	return(SendChar(ch));
}

/*Redirect Scanf functions*/

int fgetc(FILE*f)
{
	return(SendChar(GetKey()));
	/*When calling scanf() to input data in the serial port, it must end with a space, otherwise the sending cannot be completed*/
}

void _ttywrch(int ch)
{
	SendChar(ch);
}

int _ferror(FILE*f)
{
	/*Yourimplementationofferror*/
	return EOF;
}

#endif


int SendChar(int ch)
{
	while(!(USART1->SR&USART_FLAG_TXE));
	USART1->DR=(ch&0x1FF);
	return ch;
}

int GetKey(void)
{
	while(!(USART1->SR&USART_FLAG_RXNE));
	return((int)(USART1->DR&0X1FF));
}

!! Note that when using the scanf() function for input, please do not interrupt USATR, otherwise it will not be received. The printf() function has no restrictions.

The red box in the figure below doesn't appear. I just open the interrupt. Although I haven't written the interrupt function, I can't receive it by using scanf() function. It's easy to use without writing the interrupt. I don't know why or whether it's an example.

Published 11 original articles, won praise 3, visited 2455
Private letter follow

Added by Ardivaba on Fri, 14 Feb 2020 00:09:30 +0200