Blame | Last modification | View Log | Download
/*! \file uart2.c \brief Dual UART driver with buffer support. *///*****************************************************************************//// File Name : 'uart2.c'// Title : Dual UART driver with buffer support// Author : Pascal Stang - Copyright (C) 2000-2004// Created : 11/20/2000// Revised : 07/04/2004// Version : 1.0// Target MCU : ATMEL AVR Series// Editor Tabs : 4//// Description : This is a UART driver for AVR-series processors with two// hardware UARTs such as the mega161 and mega128//// 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 "uart2.h"// UART global variables// flag variablesvolatile u08 uartReadyTx[2];volatile u08 uartBufferedTx[2];// receive and transmit bufferscBuffer uartRxBuffer[2];cBuffer uartTxBuffer[2];unsigned short uartRxOverflow[2];#ifndef UART_BUFFER_EXTERNAL_RAM// using internal ram,// automatically allocate space in ram for each bufferstatic char uart0RxData[UART0_RX_BUFFER_SIZE];static char uart0TxData[UART0_TX_BUFFER_SIZE];static char uart1RxData[UART1_RX_BUFFER_SIZE];static char uart1TxData[UART1_TX_BUFFER_SIZE];#endiftypedef void (*voidFuncPtru08)(unsigned char);volatile static voidFuncPtru08 UartRxFunc[2];void uartInit(void){// initialize both uartsuart0Init();uart1Init();}void uart0Init(void){// initialize the buffersuart0InitBuffers();// initialize user receive handlersUartRxFunc[0] = 0;// enable RxD/TxD and interruptsoutb(UCSR0B, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));// set default baud rateuartSetBaudRate(0, UART0_DEFAULT_BAUD_RATE);// initialize statesuartReadyTx[0] = TRUE;uartBufferedTx[0] = FALSE;// clear overflow countuartRxOverflow[0] = 0;// enable interruptssei();}void uart1Init(void){// initialize the buffersuart1InitBuffers();// initialize user receive handlersUartRxFunc[1] = 0;// enable RxD/TxD and interruptsoutb(UCSR1B, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));// set default baud rateuartSetBaudRate(1, UART1_DEFAULT_BAUD_RATE);// initialize statesuartReadyTx[1] = TRUE;uartBufferedTx[1] = FALSE;// clear overflow countuartRxOverflow[1] = 0;// enable interruptssei();}void uart0InitBuffers(void){#ifndef UART_BUFFER_EXTERNAL_RAM// initialize the UART0 buffersbufferInit(&uartRxBuffer[0], uart0RxData, UART0_RX_BUFFER_SIZE);bufferInit(&uartTxBuffer[0], uart0TxData, UART0_TX_BUFFER_SIZE);#else// initialize the UART0 buffersbufferInit(&uartRxBuffer[0], (u08*) UART0_RX_BUFFER_ADDR, UART0_RX_BUFFER_SIZE);bufferInit(&uartTxBuffer[0], (u08*) UART0_TX_BUFFER_ADDR, UART0_TX_BUFFER_SIZE);#endif}void uart1InitBuffers(void){#ifndef UART_BUFFER_EXTERNAL_RAM// initialize the UART1 buffersbufferInit(&uartRxBuffer[1], uart1RxData, UART1_RX_BUFFER_SIZE);bufferInit(&uartTxBuffer[1], uart1TxData, UART1_TX_BUFFER_SIZE);#else// initialize the UART1 buffersbufferInit(&uartRxBuffer[1], (u08*) UART1_RX_BUFFER_ADDR, UART1_RX_BUFFER_SIZE);bufferInit(&uartTxBuffer[1], (u08*) UART1_TX_BUFFER_ADDR, UART1_TX_BUFFER_SIZE);#endif}void uartSetRxHandler(u08 nUart, void (*rx_func)(unsigned char c)){// make sure the uart number is within boundsif(nUart < 2){// set the receive interrupt to run the supplied user functionUartRxFunc[nUart] = rx_func;}}void uartSetBaudRate(u08 nUart, u32 baudrate){// calculate division factor for requested baud rate, and set itu16 bauddiv = ((F_CPU+(baudrate*8L))/(baudrate*16L)-1);if(nUart){outb(UBRR1L, bauddiv);#ifdef UBRR1Houtb(UBRR1H, bauddiv>>8);#endif}else{outb(UBRR0L, bauddiv);#ifdef UBRR0Houtb(UBRR0H, bauddiv>>8);#endif}}cBuffer* uartGetRxBuffer(u08 nUart){// return rx buffer pointerreturn &uartRxBuffer[nUart];}cBuffer* uartGetTxBuffer(u08 nUart){// return tx buffer pointerreturn &uartTxBuffer[nUart];}void uartSendByte(u08 nUart, u08 txData){// wait for the transmitter to be ready// while(!uartReadyTx[nUart]);// send byteif(nUart){while(!(UCSR1A & (1<<UDRE)));outb(UDR1, txData);}else{while(!(UCSR0A & (1<<UDRE)));outb(UDR0, txData);}// set ready state to FALSEuartReadyTx[nUart] = FALSE;}void uart0SendByte(u08 data){// send byte on UART0uartSendByte(0, data);}void uart1SendByte(u08 data){// send byte on UART1uartSendByte(1, data);}int uart0GetByte(void){// get single byte from receive buffer (if available)u08 c;if(uartReceiveByte(0,&c))return c;elsereturn -1;}int uart1GetByte(void){// get single byte from receive buffer (if available)u08 c;if(uartReceiveByte(1,&c))return c;elsereturn -1;}u08 uartReceiveByte(u08 nUart, u08* rxData){// make sure we have a receive bufferif(uartRxBuffer[nUart].size){// make sure we have dataif(uartRxBuffer[nUart].datalength){// get byte from beginning of buffer*rxData = bufferGetFromFront(&uartRxBuffer[nUart]);return TRUE;}elsereturn FALSE; // no data}elsereturn FALSE; // no buffer}void uartFlushReceiveBuffer(u08 nUart){// flush all data from receive bufferbufferFlush(&uartRxBuffer[nUart]);}u08 uartReceiveBufferIsEmpty(u08 nUart){return (uartRxBuffer[nUart].datalength == 0);}void uartAddToTxBuffer(u08 nUart, u08 data){// add data byte to the end of the tx bufferbufferAddToEnd(&uartTxBuffer[nUart], data);}void uart0AddToTxBuffer(u08 data){uartAddToTxBuffer(0,data);}void uart1AddToTxBuffer(u08 data){uartAddToTxBuffer(1,data);}void uartSendTxBuffer(u08 nUart){// turn on buffered transmituartBufferedTx[nUart] = TRUE;// send the first byte to get things going by interruptsuartSendByte(nUart, bufferGetFromFront(&uartTxBuffer[nUart]));}u08 uartSendBuffer(u08 nUart, 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[nUart].datalength + nBytes < uartTxBuffer[nUart].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[nUart], *buffer++);}// send the first byte to get things going by interruptsuartBufferedTx[nUart] = TRUE;uartSendByte(nUart, first);// return successreturn TRUE;}else{// return failurereturn FALSE;}}// UART Transmit Complete Interrupt Functionvoid uartTransmitService(u08 nUart){// check if buffered tx is enabledif(uartBufferedTx[nUart]){// check if there's data left in the bufferif(uartTxBuffer[nUart].datalength){// send byte from top of bufferif(nUart)outb(UDR1, bufferGetFromFront(&uartTxBuffer[1]) );elseoutb(UDR0, bufferGetFromFront(&uartTxBuffer[0]) );}else{// no data leftuartBufferedTx[nUart] = FALSE;// return to ready stateuartReadyTx[nUart] = TRUE;}}else{// we're using single-byte tx mode// indicate transmit complete, back to readyuartReadyTx[nUart] = TRUE;}}// UART Receive Complete Interrupt Functionvoid uartReceiveService(u08 nUart){u08 c;// get received charif(nUart)c = inb(UDR1);elsec = inb(UDR0);// if there's a user function to handle this receive eventif(UartRxFunc[nUart]){// call it and pass the received dataUartRxFunc[nUart](c);}else{// otherwise do default processing// put received char in buffer// check if there's spaceif( !bufferAddToEnd(&uartRxBuffer[nUart], c) ){// no space in buffer// count overflowuartRxOverflow[nUart]++;}}}UART_INTERRUPT_HANDLER(SIG_UART0_TRANS){// service UART0 transmit interruptuartTransmitService(0);}UART_INTERRUPT_HANDLER(SIG_UART1_TRANS){// service UART1 transmit interruptuartTransmitService(1);}UART_INTERRUPT_HANDLER(SIG_UART0_RECV){// service UART0 receive interruptuartReceiveService(0);}UART_INTERRUPT_HANDLER(SIG_UART1_RECV){// service UART1 receive interruptuartReceiveService(1);}