Writing a simple UART library
Objective
In a previous post, I explained how to make AVR communicate with my PC using UART. Since I will be using UART in other projects, I wanted to write a simple library for my own use.
What functions should this library have? To begin with:
- Initialize UART
- Transit a byte to a receiver
- Receive a byte from a transmitter
- Print a string
- Print a byte as a number
I will primarily use this library to print to a console for debugging purposes, so these functions should suffice. I will add more when the need arises.
Code
My code is broken down into myUART.c and myUART.h
-
// myUART.c void initUART(int baud) { // Calculate UBBR uint16_t baud_setting = (F_CPU / 16 / baud) - 1; // Set BAUD UBRR0H = baud_setting >> 8; UBRR0L = baud_setting; // Set Transmitter/Receiver enable UCSR0B |= (1 << TXEN0) | (1 << RXEN0); // Set 8 data bits and 1 stop bit UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01); }
First, we set Baudrate using
F_CPU
andbaud
using the formula from the datasheet. Macro F_CPU holds the clock frequency and needs to be defined for this to work. Then we enable Transmitter/Receiver, and set data format. -
void transmitByte(uint8_t ch) { while (!(UCSR0A & (1 << UDRE0))); UDR0 = ch; }
Run a blocking loop until Data Registery Empty
UDRE0
flag bit is set. Then, write the byte to Data RegisterUDR0
. -
uint8_t receiveByte(void) { while (!(UCSR0A & (1 << RXC0))); return UDR0; }
Run a blocking loop until Receive complete
RXC0
bit is set. Then, return the byte from Data RegisterUDR0
. -
void printString(const char myString[]) { for (int i = 0; myString[i]; i++) { transmitByte(myString[i]); } }
Loop over the string and use
transmitByte()
to send one byte at a time. -
void printByte(uint8_t ch) { transmitByte('0' + (ch / 100)); transmitByte('0' + ((ch / 10) % 10)); transmitByte('0' + (ch % 10)); }
Transmit ASCII code of each decimal digit of the byte.
Complete Code
#include <avr/io.h>
#include "myUART.h"
// Initialization
void initUART(int baud) {
// Calculate UBBR
uint16_t baud_setting = (F_CPU / 16 / baud) - 1;
// Set BAUD
UBRR0H = baud_setting >> 8;
UBRR0L = baud_setting;
// Set Transmitter/Receiver enable
UCSR0B |= (1 << TXEN0) | (1 << RXEN0);
// Set 8 data bits and 1 stop bit
UCSR0C |= (1 << UCSZ00) | (1 << UCSZ01);
}
// Transmitting functions
void transmitByte(uint8_t ch) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = ch;
}
// Receiving functions
uint8_t receiveByte(void) {
while (!(UCSR0A & (1 << RXC0)));
return UDR0;
}
// Printing functions
void printString(const char myString[]) {
for (int i = 0; myString[i]; i++)
{
transmitByte(myString[i]);
}
}
void printByte(uint8_t ch) {
transmitByte('0' + (ch / 100));
transmitByte('0' + ((ch / 10) % 10));
transmitByte('0' + (ch % 10));
}