AVR serial library
Simple AVR serial library with circular buffer for ATmega88/168/328.
serial.h
#ifndef SERIAL_H
#define SERIAL_H
#include <stdio.h>
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE ((F_CPU / 16 + USART_BAUDRATE / 2) / USART_BAUDRATE - 1)
const int serialBufferSize = 64;
void serialInit();
int serialWriteChar(char ch);
int serialWriteChar(char ch, FILE *stream);
bool serialBufferEmpty();
char serialRead();
uint8_t serialAvailable();
char serialPeek();
#endif
serial.cpp
#include <avr/interrupt.h>
#include <util/delay.h>
#include "serial.h"
volatile char serialBuffer[serialBufferSize];
volatile uint8_t serialBufferStart = 0;
volatile uint8_t serialBufferEnd = 0;
static FILE uartstdout = {0};
void serialInit() {
UBRR0H = (unsigned char)(BAUD_PRESCALE >> 8);
UBRR0L = (unsigned char)(BAUD_PRESCALE);
// Enable receive and transmit
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
UCSR0C = (3 << UCSZ00);
// Set serialWriteChar as stdout
fdev_setup_stream(&uartstdout, serialWriteChar, NULL, _FDEV_SETUP_WRITE);
stdout = &uartstdout;
}
int serialWriteChar(char ch) {
while (!(UCSR0A & (1 << UDRE0)));
UDR0 = ch;
return 0;
}
int serialWriteChar(char ch, FILE *stream) {
return serialWriteChar(ch);
}
ISR(USART_RX_vect) {
serialBuffer[serialBufferEnd] = UDR0;
serialBufferEnd = (serialBufferEnd + 1) % serialBufferSize;
if (serialBufferEnd == serialBufferStart) { // wrapped around, replacing earlier start value.
serialBufferStart = (serialBufferStart + 1) % serialBufferSize;
}
}
bool serialBufferEmpty() {
return serialBufferStart == serialBufferEnd;
}
char serialRead() {
while (serialBufferEmpty()) {
_delay_ms(50);
}
char ch = serialBuffer[serialBufferStart];
serialBufferStart = (serialBufferStart + 1) % serialBufferSize;
return ch;
}
uint8_t serialAvailable() {
return (serialBufferEnd - serialBufferStart) % serialBufferSize;
}
char serialPeek() {
if (serialAvailable()) {
return serialBuffer[serialBufferStart];
}
return '\0';
}