4 Send Formatted Strings/Send String
Templates Using printf
It is a common use case for an application to send a string with variable fields, for
example, when the application reports its state or a counter value. Using formatted
strings is a very flexible approach and reduces the number of code lines. This can be
accomplished by changing the output stream of the ‘printf
’ function.
This use case follows these steps:
- Configure the USART peripheral the same as for the first use case
- Create a used defined stream
- Replace the standard output stream with the user-defined stream
Usually, when using ‘printf
’, the characters are sent to a stream of
data, called standard output stream. On a PC, the standard output stream is handled by
the function to display characters on the screen. But streams can be created so that
another function handles their data.
The following code creates a user-defined stream that will be handled by the
USART1_printChar
function. This function is a wrapper of the
USART1_sendChar
function but has a slightly different signature to
match what FDEV_SETUP_STREAM
expects as a parameter.
static void USART1_sendChar(char c) { while (!(USART1.STATUS & USART_DREIF_bm)) { ; } USART1.TXDATAL = c; } static int USART1_printChar(char c, FILE *stream) { USART1_sendChar(c); return 0; } static FILE USART_stream = FDEV_SETUP_STREAM(USART1_printChar, NULL, _FDEV_SETUP_WRITE);
Then replace the standard output stream with the user-defined stream, handled by the USART send function.
stdout = &USART_stream;
The application can now use ‘printf
’ instead of writing to USART
registers directly.
uint8_t count = 0; while (1) { printf("Counter value is: %d\r\n", count++); _delay_ms(500); }
printf
’ function
uses specifiers to mark where to insert variables in the string template. Some of the
available specifiers are in the table below:Specifier | Description |
---|---|
%d | Insert a signed integer |
%s | Insert a sequence of characters |
%c | Insert a character |
%x | Insert integer unsigned in hex format |
Other settings do not change and are, therefore, skipped in the code snippets above. See the full code example on GitHub.
An MPLAB MCC generated code example for AVR128DA48 with the same functionality as the one described in this section can be found here: