You are here

C - AVR UART Driver

// Literatur: AVR uController Manuals
 
 
/******************************************************
 * hal.h                                              *
 ******************************************************/
    #ifndef HAL_H
    #define HAL_H
 
    // UART baudrates
    typedef enum UART_BR_e
    {	
        BR_4800,
        BR_9600,
        BR_19200,
        BR_38400,
        BR_57600,
        BR_115200,
    } UART_BR_t;
 
    // UART receiver callback
    typedef void (*UARTCALLBACK) (unsigned char data);
 
    // UART signals
    #define UART_PORT               PORTE
    #define UART_DDR                DDRE
    #define UART_RXD_PIN            0
    #define UART_TXD_PIN            1
 
    #define TX_BUFFER_SIZE			512
    #define UART_TX_BUFFER_MASK 	(TX_BUFFER_SIZE - 1)
 
    #endif
 
 
/******************************************************
 * uart.h                                             *
 ******************************************************/
    #ifndef UART_H
    #define UART_H
 
    #include <avr/pgmspace.h>
    #include "hal.h"
 
    void uart_init(tUART_BR Baudrate);
    void uart_putHex(unsigned char);
    void uart_putByte(unsigned char);
    void uart_putInt(unsigned int);
    void uart_putLong(unsigned long);
    void uart_putStr(unsigned char *);
    void uart_putData(unsigned char *, unsigned char);
    void uart_putStrf(PGM_P);
    void uart_putChar(unsigned char);
    BOOL uart_dataAvailable(void);
 
    void uart_registerCallback(UARTCALLBACK CallBack);
 
    #endif
 
 
/******************************************************
 * uart.c                                             *
 ******************************************************/
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    #include <string.h>
    #include "uart.h"
 
    // global variables
    static volatile unsigned char uart_TxBuf[TX_BUFFER_SIZE];
    static volatile unsigned char uart_TxHead = 0;
    static volatile unsigned char uart_TxTail = 0;
 
    static volatile UARTCALLBACK UartRecCallback = NULL;
 
    void UART0_RegisterCallback(UARTCALLBACK CallBack)
    {
        UartRecCallback = CallBack;
    }
 
    void uart_init(UART_BR_t Baudrate)
    {
        unsigned int UBRRVAL = 0;
 
        switch (Baudrate)
        {
        case BR_4800:
            UBRRVAL = (F_CPU/(4800L*16L)-1);
            break;
        case BR_9600:
            UBRRVAL = (F_CPU/(9600L*16L)-1);
            break;
        case BR_19200:
            UBRRVAL = (F_CPU/(19200L*16L)-1);
            break;
        case BR_38400:
            UBRRVAL = (F_CPU/(38400L*16L)-1);
            break;
        case BR_57600:
            UBRRVAL = (F_CPU/(57600L*16L)-1);
            break;
        case BR_115200:
            UBRRVAL = (F_CPU/(115200L*16L)-1);
            break;
        default:
            UBRRVAL = (F_CPU/(9600L*16L)-1);
            break;
        }	
 
        UBRR0H = (unsigned char)(UBRRVAL>>8);
        UBRR0L = (unsigned char)UBRRVAL;
 
        // enable receiver and transmitter
        UCSR0B = (1<<TXEN0)|(1<<RXEN0)|(1<<RXCIE0);
        // set frame format: 8data, 1stop bit
        UCSR0C = (3<<UCSZ00);
 
        UART0_TxHead = 0;
        UART0_TxTail = 0;
    }
 
    // send hex character via serial
    void uart_putHex(unsigned char data)
    {
        unsigned char buf[5];
        sprintf((char *)buf, "%02x", data);
        uart_putStr(buf);
    }
 
    // send a byte
    void uart_putByte(unsigned char data)
    {
        unsigned char buf[5];
        sprintf((char *)buf, "%02u", data);
        uart_putStr(buf);
    }
 
    // send an integer
    void uart_putInt(unsigned int data)
    {
        unsigned char buf[6];
        sprintf((char *)buf, "%5u", data);
        uart_putStr(buf);
    }
 
    // send a long value
    void uart_putLong(unsigned long Value)
    {
        unsigned char Cnt;
        unsigned char Buf[20];
 
        // convert
        Cnt = 10;
        do 
        {
            Cnt--;
            Buf[Cnt] = Value % 10;
            Value /= 10;
        } while (Value > 0);
 
        // output
        while (Cnt < 10)
        {
            uart_putChar(Buf[Cnt] + '0');
            Cnt++;
        }
    }
 
    // send a string
    void uart_putStr(unsigned char * pdata)
    {
        while (*pdata) 
        {
            uart_putChar(*pdata++);
        }
    }
 
    // send a string
    void uart_putData(unsigned char * pdata, unsigned char Len)
    {
        while (Len--) 
        {
            uart_putChar(*pdata++);
        }
    }
 
    // send a string from flash-memory
    void uart_putStrf(PGM_P pdata)
    {
        // while not 0 continue
        while (pgm_read_byte(pdata))
        {
            uart_putChar(pgm_read_byte(pdata++));
        }
    }                                   
 
    // send a character via serial using a ringbuffer
    void uart_putChar(unsigned char data)
    {
        unsigned char tmphead;
 
        tmphead = (uart_TxHead + 1) & UART_TX_BUFFER_MASK;
 
        uart_TxBuf[tmphead] = data;
        uart_TxHead = tmphead;
 
        // enable UDRE signal
        UCSR0B |= (1<<UDRIE0);
    }
 
 
    // serial UART data register empty signal vector
    SIGNAL (SIG_USART0_DATA)
    {
        unsigned char tmptail;
 
        if (uart_TxHead != UART0_TxTail) 
        {
            // calculate and store new buffer index
            tmptail = (uart_TxTail + 1) & UART_TX_BUFFER_MASK;
            uart_TxTail = tmptail;
 
            // get one byte from buffer and write it to UART
            UDR0 = uart_TxBuf[tmptail];
        }
        else
        {
            // tx buffer empty, disable UDRE signal
            UCSR0B &= ~(1<<UDRIE0);
        }
    }
 
    // serial UART receive complete signal vector
    SIGNAL (SIG_USART0_RECV)
    {
        if (UartRecCallback != NULL)
        {
            UartRecCallback(UDR0);
        }
    }