/*
š§ How This Works
1. UBRR0H/UBRR0L: Combined 16-bit register that sets the baud rate divisor.
2. UCSR0A: Status flags. UDRE0 tells us when the transmit buffer is empty.
3. UCSR0B: Enables TX/RX circuitry.
4. UCSR0C: Sets the frame format (e.g., 8 data bits, 1 stop bit, no parity).
5. UDR0: The I/O register used to send/receive a byte.
*/
#define F_CPU 16000000UL // 16 MHz external crystal
#include <avr/io.h>
#include <util/delay.h>
// Set desired baud rate here
// See datasheet page 148: 19.5 USART Initialization
#define BAUD 9600
#define MYUBRR F_CPU/16/BAUD-1 // Formula from datasheet (U2Xn = 0)
void USART_init(unsigned int ubrr) {
// Set baud rate
UBRR0H = (unsigned char)(ubrr >> 8); // Upper 8 bits of UBRR
UBRR0L = (unsigned char)ubrr; // Lower 8 bits
// Enable transmitter (TX) and receiver (RX)
UCSR0B = (1 << TXEN0) | (1 << RXEN0);
// Set frame format: 8 data bits, 1 stop bit, no parity
UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // UCSZn1:0 = 3 ā 8-bit
}
void USART_transmit(unsigned char data) {
// Wait for the transmit buffer to be empty
while (!(UCSR0A & (1 << UDRE0)));
// Put data into buffer -> sends the data
UDR0 = data;
}
void USART_print(const char *str) {
while (*str) {
USART_transmit(*str++);
}
}
int main(void) {
USART_init(MYUBRR); // Initialize USART with calculated UBRR
while (1) {
USART_print("Hello, World!\n");
_delay_ms(1000); // Wait a second
USART_print("Next line please\n");
_delay_ms(1000); // Wait a second
}
}