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'; }