Main Page   Data Structures   File List   Data Fields   Globals  

/uart.c

Go to the documentation of this file.
00001 /*! \file uart.c \brief UART driver with buffer support. */
00002 // *****************************************************************************
00003 //
00004 // File Name    : 'uart.c'
00005 // Title        : UART driver with buffer support
00006 // Author       : Pascal Stang - Copyright (C) 2000-2002
00007 // Created      : 11/22/2000
00008 // Revised      : 06/09/2003
00009 // Version      : 1.3
00010 // Target MCU   : ATMEL AVR Series
00011 // Editor Tabs  : 4
00012 //
00013 // This code is distributed under the GNU Public License
00014 //      which can be found at http://www.gnu.org/licenses/gpl.txt
00015 //
00016 // *****************************************************************************
00017 
00018 #include <avr/io.h>
00019 #include <avr/interrupt.h>
00020 #include <avr/signal.h>
00021 
00022 #include "buffer.h"
00023 #include "uart.h"
00024 
00025 // UART global variables
00026 // flag variables
00027 volatile u08   uartReadyTx;         ///< uartReadyTx flag
00028 volatile u08   uartBufferedTx;      ///< uartBufferedTx flag
00029 // receive and transmit buffers
00030 cBuffer uartRxBuffer;               ///< uart receive buffer
00031 cBuffer uartTxBuffer;               ///< uart transmit buffer
00032 unsigned short uartRxOverflow;      ///< receive overflow counter
00033 
00034 #ifndef UART_BUFFERS_EXTERNAL_RAM
00035     // using internal ram,
00036     // automatically allocate space in ram for each buffer
00037     static char uartRxData[UART_RX_BUFFER_SIZE];
00038     static char uartTxData[UART_TX_BUFFER_SIZE];
00039 #endif
00040 
00041 typedef void (*voidFuncPtru08)(unsigned char);
00042 volatile static voidFuncPtru08 UartRxFunc;
00043 
00044 //! enable and initialize the uart
00045 void uartInit(void)
00046 {
00047     // initialize the buffers
00048     uartInitBuffers();
00049     // initialize user receive handler
00050     UartRxFunc = 0;
00051 
00052     // enable RxD/TxD and interrupts
00053     #ifdef UCR
00054         // this line for AT90S8515,8535,ATmega103,etc
00055         outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));
00056     #endif
00057     #ifdef UCSRB
00058         // this line for the Mega163
00059         outb(UCSRB, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));
00060     #endif
00061     #ifdef UCSR0B
00062         // this line for dual-uart proessors like the Mega161/Mega128
00063         outb(UCSR0B, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));
00064     #endif
00065 
00066     // set default baud rate
00067     uartSetBaudRate(UART_DEFAULT_BAUD_RATE);  
00068     // initialize states
00069     uartReadyTx = TRUE;
00070     uartBufferedTx = FALSE;
00071     // clear overflow count
00072     uartRxOverflow = 0;
00073     // enable interrupts
00074     sei();
00075 }
00076 
00077 //! create and initialize the uart transmit and receive buffers
00078 void uartInitBuffers(void)
00079 {
00080     #ifndef UART_BUFFERS_EXTERNAL_RAM
00081         // initialize the UART receive buffer
00082         bufferInit(&uartRxBuffer, uartRxData, UART_RX_BUFFER_SIZE);
00083         // initialize the UART transmit buffer
00084         bufferInit(&uartTxBuffer, uartTxData, UART_TX_BUFFER_SIZE);
00085     #else
00086         // initialize the UART receive buffer
00087         bufferInit(&uartRxBuffer, (u08*) UART_RX_BUFFER_ADDR, UART_RX_BUFFER_SIZE);
00088         // initialize the UART transmit buffer
00089         bufferInit(&uartTxBuffer, (u08*) UART_TX_BUFFER_ADDR, UART_TX_BUFFER_SIZE);
00090     #endif
00091 }
00092 
00093 //! redirects received data to a user function
00094 void uartSetRxHandler(void (*rx_func)(unsigned char c))
00095 {
00096     // set the receive interrupt to run the supplied user function
00097     UartRxFunc = rx_func;
00098 }
00099 
00100 //! set the uart baud rate
00101 void uartSetBaudRate(u32 baudrate)
00102 {
00103     // calculate division factor for requested baud rate, and set it
00104     outb(UBRR, (u08)((F_CPU+(baudrate*8L))/(baudrate*16L)-1));
00105 }
00106 
00107 //! returns the receive buffer structure 
00108 cBuffer* uartGetRxBuffer(void)
00109 {
00110     // return rx buffer pointer
00111     return &uartRxBuffer;
00112 }
00113 
00114 //! returns the transmit buffer structure 
00115 cBuffer* uartGetTxBuffer(void)
00116 {
00117     // return tx buffer pointer
00118     return &uartTxBuffer;
00119 }
00120 
00121 //! transmits a byte over the uart
00122 void uartSendByte(u08 txData)
00123 {
00124     // wait for the transmitter to be ready
00125     while(!uartReadyTx);
00126     // send byte
00127     outp( txData, UDR );
00128     // set ready state to FALSE
00129     uartReadyTx = FALSE;
00130 }
00131 
00132 //! gets a byte (if available) from the uart receive buffer
00133 u08 uartReceiveByte(u08* rxData)
00134 {
00135     // make sure we have a receive buffer
00136     if(uartRxBuffer.size)
00137     {
00138         // make sure we have data
00139         if(uartRxBuffer.datalength)
00140         {
00141             // get byte from beginning of buffer
00142             *rxData = bufferGetFromFront(&uartRxBuffer);
00143             return TRUE;
00144         }
00145         else
00146         {
00147             // no data
00148             return FALSE;
00149         }
00150     }
00151     else
00152     {
00153         // no buffer
00154         return FALSE;
00155     }
00156 }
00157 
00158 //! flush all data out of the receive buffer
00159 void uartFlushReceiveBuffer(void)
00160 {
00161     // flush all data from receive buffer
00162     bufferFlush(&uartRxBuffer);
00163     // same effect as above
00164     // uartRxBuffer.datalength = 0;
00165 }
00166 
00167 //! return true if uart receive buffer is empty
00168 u08 uartReceiveBufferIsEmpty(void)
00169 {
00170     if(uartRxBuffer.datalength == 0)
00171     {
00172         return TRUE;
00173     }
00174     else
00175     {
00176         return FALSE;
00177     }
00178 }
00179 
00180 //! add byte to end of uart Tx buffer
00181 void uartAddToTxBuffer(u08 data)
00182 {
00183     // add data byte to the end of the tx buffer
00184     bufferAddToEnd(&uartTxBuffer, data);
00185 }
00186 
00187 //! start transmission of the current uart Tx buffer contents
00188 void uartSendTxBuffer(void)
00189 {
00190     // turn on buffered transmit
00191     uartBufferedTx = TRUE;
00192     // send the first byte to get things going by interrupts
00193     uartSendByte(bufferGetFromFront(&uartTxBuffer));
00194 }
00195 
00196 //! transmit nBytes from buffer out the uart
00197 u08 uartSendBuffer(char *buffer, u16 nBytes)
00198 {
00199     register u08 first;
00200     register u16 i;
00201 
00202     // check if there's space (and that we have any bytes to send at all)
00203     if((uartTxBuffer.datalength + nBytes < uartTxBuffer.size) && nBytes)
00204     {
00205         // grab first character
00206         first = *buffer++;
00207         // copy user buffer to uart transmit buffer
00208         for(i = 0; i < nBytes-1; i++)
00209         {
00210             // put data bytes at end of buffer
00211             bufferAddToEnd(&uartTxBuffer, *buffer++);
00212         }
00213 
00214         // send the first byte to get things going by interrupts
00215         uartBufferedTx = TRUE;
00216         uartSendByte(first);
00217         // return success
00218         return TRUE;
00219     }
00220     else
00221     {
00222         // return failure
00223         return FALSE;
00224     }
00225 }
00226 
00227 //! UART Transmit Complete Interrupt Handler
00228 UART_INTERRUPT_HANDLER(SIG_UART_TRANS)
00229 {
00230     // check if buffered tx is enabled
00231     if(uartBufferedTx)
00232     {
00233         // check if there's data left in the buffer
00234         if(uartTxBuffer.datalength)
00235         {
00236             // send byte from top of buffer
00237             outp( bufferGetFromFront(&uartTxBuffer), UDR );
00238         }
00239         else
00240         {
00241             // no data left
00242             uartBufferedTx = FALSE;
00243             // return to ready state
00244             uartReadyTx = TRUE;
00245         }
00246     }
00247     else
00248     {
00249         // we're using single-byte tx mode
00250         // indicate transmit complete, back to ready
00251         uartReadyTx = TRUE;
00252     }
00253 }
00254 
00255 //! UART Receive Complete Interrupt Handler
00256 UART_INTERRUPT_HANDLER(SIG_UART_RECV)
00257 {
00258     u08 c;
00259     
00260     // get received char
00261     c = inp(UDR);
00262 
00263     // if there's a user function to handle this receive event
00264     if(UartRxFunc)
00265     {
00266         // call it and pass the received data
00267         UartRxFunc(c);
00268     }
00269     else
00270     {
00271         // otherwise do default processing
00272         // put received char in buffer
00273         // check if there's space
00274         if( !bufferAddToEnd(&uartRxBuffer, c) )
00275         {
00276             // no space in buffer
00277             // count overflow
00278             uartRxOverflow++;
00279         }
00280     }
00281 }

Generated on Fri Aug 1 10:42:42 2003 for Procyon AVRlib by doxygen1.2.18