Die UART Library ist ein Port der Application Note AVR306 für den avr-gcc. Die Library verwendet Interrupts und hat je einen Buffer für Receive und Transmit. Die Original-Library stammt von Peter Fleury und wurde vom mir abgespeckt und um eine Funktion erweitert. Die vorliegende Library ist für den ATMEGA8 und ATMEGA16 geschrieben, kann aber auf andere AVRs angepasst werden. Ensprechende Hinweise sind im Quelltext vorhanden.
uart_init()
Es wird der UART des ATMEGA8 mit der in der uart.h angegebenen Baudrate, 8 Datenbits, 1 Stopbit und keine Parität initialisiert.
uart_data_received()
Die Funktion uart_data_received() fragt ab ob der Buffer Daten empfangen hat. Ist der Buffer leer liefert die Funktion 0 (False).
uart_getc()
Die Funktion uart_getc() liefert ein Zeichen aus dem Receive-Buffer. Es wird der Receive-Buffer nicht überprüft. Dies kann mit der Funktion uart_data_received() erfolgen.
uart_putc()
Die Funktion uart_putc() sendet ein Zeichen an den Transmit-Buffer. Sollte der Buffer voll sein wartet die Funktion bis ein Zeichen frei ist.
uart_puts()
Die Funktion uart_puts() sendet einen String an den Transmit-Buffer über die Funktion uart_putc(). Es gilt dasselbe wie bei uart_putc().
In der Datei uart.h kann die Buffergröße für Receive und Transmit angegeben werden. Die Buffergrößte kann 2, 4, 8, 16, 32, 64, 128 oder 256 Byte groß sein.
#include <avr/io.h> #include <avr/interrupt.h> #include "uart.h" unsigned char temp; int main (void) { uart_init(); sei(); uart_puts("Hallo Welt"); //Ausgabe "Hallo Welt" while (1) { if (uart_data_received()) //es sind Daten im Empfangspuffer { temp = uart_getc(); //diese empfangen uart_putc(temp); //und über den Sendepuffer ausgeben } } return 0; }
/* * uart.h * * Copyright 2008 Ronny Schmiedel <http://avrs-at-leipzig.de> * * Original from Peter Fleury <http://homepage.hispeed.ch/peterfleury/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * AVR306: Using the AVR UART in C using IRQ * Port for AVR GCC/WinAVR * Routines for interrupt controlled USART * Supports ATMEGA8, ATMEGA16 * Last Edit: 02.01.2009 */ #ifndef UART_H #define UART_H /* UART Buffer Defines */ #define UART_RX_BUFFER_SIZE 32 /* 2,4,8,16,32,64,128 or 256 bytes */ #define UART_TX_BUFFER_SIZE 32 /* 2,4,8,16,32,64,128 or 256 bytes */ #define UART_RX_BUFFER_MASK ( UART_RX_BUFFER_SIZE - 1 ) #define UART_TX_BUFFER_MASK ( UART_TX_BUFFER_SIZE - 1 ) #if ( UART_RX_BUFFER_SIZE & UART_RX_BUFFER_MASK ) #error RX buffer size is not a power of 2 #endif #if ( UART_TX_BUFFER_SIZE & UART_TX_BUFFER_MASK ) #error TX buffer size is not a power of 2 #endif #define UART_BAUD_RATE 9600 /* Prototypes */ /** * @brief Initialize USART * @return void */ extern void uart_init (void); /** * @brief Receives Char from USART Buffer * @param void * @return char */ extern unsigned char uart_getc( void ); /** * @brief Sends Char to USART Buffer * @param Char to send * @void */ extern void uart_putc( unsigned char data ); /** * @brief Sends String to USART Buffer * @param Char to send * @void */ extern void uart_puts(const char *s ); /** * @brief Test if received char is in Buffer * @param void * @return Return 0 (FALSE) if the receive buffer is empty */ extern char uart_data_received( void ); #endif
/* * uart.c * * Copyright 2008 Ronny Schmiedel <http://avrs-at-leipzig.de> * * Original from Peter Fleury <http://homepage.hispeed.ch/peterfleury/> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. * * AVR306: Using the AVR UART in C using IRQ * Port for AVR GCC/WinAVR * Routines for interrupt controlled USART * Supports ATMEGA8, ATMEGA16 * Last Edit: 02.01.2009 */ /* Includes */ #include <avr/io.h> #include <avr/interrupt.h> #include "uart.h" #define UBRR_BAUD ((F_CPU/(16L*UART_BAUD_RATE))-1) /* Static Variables */ static volatile unsigned char UART_TxBuf[UART_TX_BUFFER_SIZE]; static volatile unsigned char UART_RxBuf[UART_RX_BUFFER_SIZE]; static volatile unsigned char UART_TxHead; static volatile unsigned char UART_TxTail; static volatile unsigned char UART_RxHead; static volatile unsigned char UART_RxTail; /* Initialize USART */ void uart_init(void) { /* Special for ATMEGA8, ATMEGA16 */ UCSRB = (( 1 << RXCIE ) | ( 1 << RXEN ) | ( 1 << TXEN )); UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); UBRRH = (uint8_t) (UBRR_BAUD>>8); UBRRL = (uint8_t) (UBRR_BAUD & 0xFF); /* Flush receive buffer */ UART_RxTail = 0; UART_RxHead = 0; UART_TxTail = 0; UART_TxHead = 0; } /* Interrupt handlers */ //*****Empfang der Daten***** SIGNAL(SIG_UART_RECV) /* change ISR-Name for another AVR */ { unsigned char data; unsigned char tmphead; /* Read the received data */ data = UDR; /* Calculate buffer index */ tmphead = ( UART_RxHead + 1 ) & UART_RX_BUFFER_MASK; if ( tmphead == UART_RxTail ) { /* ERROR! Receive buffer overflow */ } else { /* store new index */ UART_RxHead = tmphead; /* store received data in buffer */ UART_RxBuf[tmphead] = data; } } //********Senden der Daten**** SIGNAL(SIG_UART_DATA) /* change ISR-Name for another AVR */ { unsigned char tmptail; /* Check if all data is transmitted */ if ( UART_TxHead != UART_TxTail ) { /* Calculate buffer index */ tmptail = ( UART_TxTail + 1 ) & UART_TX_BUFFER_MASK; UART_TxTail = tmptail; /* Store new index */ UDR = UART_TxBuf[tmptail]; /* Start transmition */ } else { /* Disable UDRE interrupt, Special ATMEGA8, ATMEGA16 */ UCSRB &= ~(1<<UDRIE); } } /* Read and write functions */ unsigned char uart_getc( void ) { unsigned char tmptail; unsigned char data; /* calculate /store buffer index */ tmptail = (UART_RxTail + 1) & UART_RX_BUFFER_MASK; UART_RxTail = tmptail; /* get data from receive buffer */ data = UART_RxBuf[tmptail]; return data; } void uart_putc( unsigned char data ) { unsigned char tmphead; tmphead = (UART_TxHead + 1) & UART_TX_BUFFER_MASK; while ( tmphead == UART_TxTail ) { ;/* wait for free space in buffer */ } UART_TxBuf[tmphead] = data; UART_TxHead = tmphead; /* Enable UDRE interrupt, special for ATMEGA8, ATMEGA16 */ UCSRB |= (1<<UDRIE); } /* uart_putc */ char uart_data_received( void ) { /* Return 0 (FALSE) if the receive buffer is empty */ return ( UART_RxHead != UART_RxTail ); } void uart_puts(const char *s ) { while (*s) uart_putc(*s++); }/* uart_puts */