Blame | Last modification | View Log | Download
/*! \file uart.c \brief UART driver with buffer support. */// *****************************************************************************//// File Name : 'uart.c'// Title : UART driver with buffer support// Author : Pascal Stang - Copyright (C) 2000-2002// Created : 11/22/2000// Revised : 06/09/2003// Version : 1.3// Target MCU : ATMEL AVR Series// Editor Tabs : 4//// This code is distributed under the GNU Public License// which can be found at http://www.gnu.org/licenses/gpl.txt//// *****************************************************************************#include <avr/io.h>#include <avr/interrupt.h>#include "buffer.h"#include "uart.h"// UART global variables// flag variablesvolatile u08 uartReadyTx; ///< uartReadyTx flagvolatile u08 uartBufferedTx; ///< uartBufferedTx flag// receive and transmit bufferscBuffer uartRxBuffer; ///< uart receive buffercBuffer uartTxBuffer; ///< uart transmit bufferunsigned short uartRxOverflow; ///< receive overflow counter#ifndef UART_BUFFERS_EXTERNAL_RAM// using internal ram,// automatically allocate space in ram for each bufferstatic char uartRxData[UART_RX_BUFFER_SIZE];static char uartTxData[UART_TX_BUFFER_SIZE];#endiftypedef void (*voidFuncPtru08)(unsigned char);volatile static voidFuncPtru08 UartRxFunc;// enable and initialize the uartvoid uartInit(void){// initialize the buffersuartInitBuffers();// initialize user receive handlerUartRxFunc = 0;// enable RxD/TxD and interruptsoutb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));// set default baud rateuartSetBaudRate(UART_DEFAULT_BAUD_RATE);// initialize statesuartReadyTx = TRUE;uartBufferedTx = FALSE;// clear overflow countuartRxOverflow = 0;// enable interruptssei();}// create and initialize the uart transmit and receive buffersvoid uartInitBuffers(void){#ifndef UART_BUFFERS_EXTERNAL_RAM// initialize the UART receive bufferbufferInit(&uartRxBuffer, uartRxData, UART_RX_BUFFER_SIZE);// initialize the UART transmit bufferbufferInit(&uartTxBuffer, uartTxData, UART_TX_BUFFER_SIZE);#else// initialize the UART receive bufferbufferInit(&uartRxBuffer, (u08*) UART_RX_BUFFER_ADDR, UART_RX_BUFFER_SIZE);// initialize the UART transmit bufferbufferInit(&uartTxBuffer, (u08*) UART_TX_BUFFER_ADDR, UART_TX_BUFFER_SIZE);#endif}// redirects received data to a user functionvoid uartSetRxHandler(void (*rx_func)(unsigned char c)){// set the receive interrupt to run the supplied user functionUartRxFunc = rx_func;}// set the uart baud ratevoid uartSetBaudRate(u32 baudrate){// calculate division factor for requested baud rate, and set itu16 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);outb(UBRRL, bauddiv);#ifdef UBRRHoutb(UBRRH, bauddiv>>8);#endif}// returns the receive buffer structurecBuffer* uartGetRxBuffer(void){// return rx buffer pointerreturn &uartRxBuffer;}// returns the transmit buffer structurecBuffer* uartGetTxBuffer(void){// return tx buffer pointerreturn &uartTxBuffer;}// transmits a byte over the uartvoid uartSendByte(u08 txData){// wait for the transmitter to be readywhile(!uartReadyTx);// send byteoutb(UDR, txData);// set ready state to FALSEuartReadyTx = FALSE;}// gets a single byte from the uart receive buffer (getchar-style)int uartGetByte(void){u08 c;if(uartReceiveByte(&c))return c;elsereturn -1;}// gets a byte (if available) from the uart receive bufferu08 uartReceiveByte(u08* rxData){// make sure we have a receive bufferif(uartRxBuffer.size){// make sure we have dataif(uartRxBuffer.datalength){// get byte from beginning of buffer*rxData = bufferGetFromFront(&uartRxBuffer);return TRUE;}else{// no datareturn FALSE;}}else{// no bufferreturn FALSE;}}// flush all data out of the receive buffervoid uartFlushReceiveBuffer(void){// flush all data from receive buffer//bufferFlush(&uartRxBuffer);// same effect as aboveuartRxBuffer.datalength = 0;}// return true if uart receive buffer is emptyu08 uartReceiveBufferIsEmpty(void){if(uartRxBuffer.datalength == 0){return TRUE;}else{return FALSE;}}// add byte to end of uart Tx bufferu08 uartAddToTxBuffer(u08 data){// add data byte to the end of the tx bufferreturn bufferAddToEnd(&uartTxBuffer, data);}// start transmission of the current uart Tx buffer contentsvoid uartSendTxBuffer(void){// turn on buffered transmituartBufferedTx = TRUE;// send the first byte to get things going by interruptsuartSendByte(bufferGetFromFront(&uartTxBuffer));}/*// transmit nBytes from buffer out the uartu08 uartSendBuffer(char *buffer, u16 nBytes){register u08 first;register u16 i;// check if there's space (and that we have any bytes to send at all)if((uartTxBuffer.datalength + nBytes < uartTxBuffer.size) && nBytes){// grab first characterfirst = *buffer++;// copy user buffer to uart transmit bufferfor(i = 0; i < nBytes-1; i++){// put data bytes at end of bufferbufferAddToEnd(&uartTxBuffer, *buffer++);}// send the first byte to get things going by interruptsuartBufferedTx = TRUE;uartSendByte(first);// return successreturn TRUE;}else{// return failurereturn FALSE;}}*/// UART Transmit Complete Interrupt HandlerUART_INTERRUPT_HANDLER(SIG_UART_TRANS){// check if buffered tx is enabledif(uartBufferedTx){// check if there's data left in the bufferif(uartTxBuffer.datalength){// send byte from top of bufferoutb(UDR, bufferGetFromFront(&uartTxBuffer));}else{// no data leftuartBufferedTx = FALSE;// return to ready stateuartReadyTx = TRUE;}}else{// we're using single-byte tx mode// indicate transmit complete, back to readyuartReadyTx = TRUE;}}// UART Receive Complete Interrupt HandlerUART_INTERRUPT_HANDLER(SIG_UART_RECV){u08 c;// get received charc = inb(UDR);// if there's a user function to handle this receive eventif(UartRxFunc){// call it and pass the received dataUartRxFunc(c);}else{// otherwise do default processing// put received char in buffer// check if there's spaceif( !bufferAddToEnd(&uartRxBuffer, c) ){// no space in buffer// count overflowuartRxOverflow++;}}}