I have a bit of code written by someone else that I'm trying to understand. I'm familiar with c enough to make basic/intermediate functions, but never really learned to use the FILE handler. The code relates to how i use/initialise the USART on an ATMEL microcontroller, and I am adding comments to every line to help keep track, but i'm struggling a little with this.
#include <stdio.h>
int USART_0_printCHAR(char character, FILE *stream) // character = the received character, FILE = reference file, *stream = pointer
{
USART_Transmit_Char(character); //send the character over USART
return 0; // return 0 to the caller for exit success.
}
FILE USART_0_stream = FDEV_SETUP_STREAM(USART_0_printCHAR, NULL, _FDEV_SETUP_WRITE); //what do these arguments mean? is it replacing a standard output stream with the character that is written to the buffer.
void USART_Transmit_Char(char data)
{
// code omitted:
// check the Transmit buffer
// wait for free space in the buffer
// put the character into the buffer
// enable the Data Register Empty Interrupt for TX
}
Thanks.
CodePudding user response:
You example initializes the default stream for the standard IO facilities. It creates a write only stream that writes its output to USART_0_printCHAR
.
The standard streams stdin, stdout, and stderr are provided, but contrary to the C standard, since avr-libc has no knowledge about applicable devices, these streams are not already pre-initialized at application startup. Also, since there is no notion of "file" whatsoever to avr-libc, there is no function fopen() that could be used to associate a stream to some device. (See note 1.) Instead, the function fdevopen() is provided to associate a stream to a device, where the device needs to provide a function to send a character, to receive a character, or both.
As an alternative method to fdevopen(), the macro fdev_setup_stream() might be used to setup a user-supplied FILE structure.
#include <stdio.h>
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);
loop_until_bit_is_set(UCSRA, UDRE);
UDR = c;
return 0;
}
int
main(void)
{
init_uart();
stdout = &mystdout;
printf("Hello, world!\n");
return 0;
}
This example uses the initializer form FDEV_SETUP_STREAM() rather than the function-like fdev_setup_stream(), so all data initialization happens during C start-up.