printfIt 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:
Normally, 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
USART0_printChar function. This function is a wrapper of the
USART_sendChar function, but has a slightly different signature to
match what FDEV_SETUP_STREAM expects as parameter.
static void USART0_sendChar(char c) { while (!(USART0.STATUS & USART_DREIF_bm)) { ; } USART0.TXDATAL = c; } static int USART0_printChar(char c, FILE *stream) { USART0_sendChar(c); return 0; } static FILE USART_stream = FDEV_SETUP_STREAM(USART0_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 placeholders to mark where to insert
variables in the string template. Some of the available placeholders are in the table
below:
| Placeholder | 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, therefore are skipped in the code snippets above. See full code example on GitHub.