6.18.1.2 Customizing Helper Functions for XC8 AVR
When using the MPLAB XC8 Compiler for AVR MCUs, helper functions that can read and/or write one
byte of data need to be written to define the source and destination respectively of the
stdin
and stdout
streams used by IO functions like
scanf()
and printf()
. In addition, objects of type
FILE
need to be defined and associated with each streams.
The FDEV_SETUP_STREAM()
macro can assist with stream configuration. It
expands to an initializer that can be used with the definition of a user-supplied buffer of
type FILE
, setting up that buffer so that it can be used with a stream that
is valid for stdio operations. Streams can be read-only, write-only, or read-write, based on
one of this macro's flag values _FDEV_SETUP_READ
,
_FDEV_SETUP_WRITE
, or _FDEV_SETUP_RW
.
The following example is applicable to the AVR128DA48 Curiosity Nano board and has writable
FILE
buffer assigned to stdout
, which maps to USART1 via
the uart_putchar()
function.
#include <xc.h>
#define F_CPU (4000000UL) /* using default clock 4MHz*/
#define USART1_BAUD_RATE(BAUD_RATE) ((float)(64 * 4000000 / (16 * (float)BAUD_RATE)) + 0.5)
#include <util/delay.h>
#include <stdio.h>
void USART1_init(void)
{
PORTC.DIRSET = PIN0_bm; /* set pin 0 of PORT C (TXd) as output*/
PORTC.DIRCLR = PIN1_bm; /* set pin 1 of PORT C (RXd) as input*/
USART1.BAUD = (uint16_t)(USART1_BAUD_RATE(9600)); /* set the baud rate*/
USART1.CTRLC = USART_CHSIZE0_bm| USART_CHSIZE1_bm; /* set the data format to 8-bit*/
USART1.CTRLB |= USART_TXEN_bm; /* enable transmitter*/
}
static int uart_putchar(char c, FILE * stream);
static FILE mystdout = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
static int
uart_putchar(char c, FILE *stream)
{
if (c == '\n')
uart_putchar('\r', stream);
while(!(USART1.STATUS & USART_DREIF_bm))
{
;
}
USART1.TXDATAL = c;
return 0;
}
int main()
{
USART1_init();
stdout = &mystdout;
int i = 0;
while (1) {
printf ("Hello world %d\n", i++);
}
_delay_ms(1000);
}