#ifndef UART_H #define UART_H /************************************************************************ Title: Interrupt UART library with receive/transmit circular buffers Author: Peter Fleury <pfleury@gmx.ch> http://jump.to/fleury File: $Id: uart.h,v 1.12 2012/11/19 19:52:27 peter Exp $ Software: AVR-GCC 4.1, AVR Libc 1.4 Hardware: any AVR with built-in UART, tested on AT90S8515 & ATmega8 at 4 Mhz License: GNU General Public License Usage: see Doxygen manual LICENSE: Copyright (C) 2006 Peter Fleury 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 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. ************************************************************************/ /** * @defgroup pfleury_uart UART Library * @code #include <uart.h> @endcode * * @brief Interrupt UART library using the built-in UART with transmit and receive circular buffers. * * This library can be used to transmit and receive data through the built in UART. * * An interrupt is generated when the UART has finished transmitting or * receiving a byte. The interrupt handling routines use circular buffers * for buffering received and transmitted data. * * The UART_RX_BUFFER_SIZE and UART_TX_BUFFER_SIZE constants define * the size of the circular buffers in bytes. Note that these constants must be a power of 2. * You may need to adapt this constants to your target and your application by adding * CDEFS += -DUART_RX_BUFFER_SIZE=nn -DUART_RX_BUFFER_SIZE=nn to your Makefile. * * @note Based on Atmel Application Note AVR306 * @author Peter Fleury pfleury@gmx.ch http://jump.to/fleury */ /**@{*/ #include <avr/pgmspace.h> #if (__GNUC__ * 100 + __GNUC_MINOR__) < 304 #error "This library requires AVR-GCC 3.4 or later, update to newer AVR-GCC compiler !" #endif /* ** constants and macros */ /** @brief UART Baudrate Expression * @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 */ #define UART_BAUD_SELECT(baudRate,xtalCpu) (((xtalCpu) + 8UL * (baudRate)) / (16UL * (baudRate)) -1UL) /** @brief UART Baudrate Expression for ATmega double speed mode * @param xtalcpu system clock in Mhz, e.g. 4000000UL for 4Mhz * @param baudrate baudrate in bps, e.g. 1200, 2400, 9600 */ #define UART_BAUD_SELECT_DOUBLE_SPEED(baudRate,xtalCpu) ( ((((xtalCpu) + 4UL * (baudRate)) / (8UL * (baudRate)) -1UL)) | 0x8000) /** Size of the circular receive buffer, must be power of 2 */ #ifndef UART_RX_BUFFER_SIZE #define UART_RX_BUFFER_SIZE 64 #endif /** Size of the circular transmit buffer, must be power of 2 */ #ifndef UART_TX_BUFFER_SIZE #define UART_TX_BUFFER_SIZE 64 #endif /* test if the size of the circular buffers fits into SRAM */ #if ( (UART_RX_BUFFER_SIZE+UART_TX_BUFFER_SIZE) >= (RAMEND-0x60 ) ) #error "size of UART_RX_BUFFER_SIZE + UART_TX_BUFFER_SIZE larger than size of SRAM" #endif /* ** high byte error return code of uart_getc() */ #define UART_FRAME_ERROR 0x1000 /* Framing Error by UART */ #define UART_OVERRUN_ERROR 0x0800 /* Overrun condition by UART */ #define UART_PARITY_ERROR 0x0400 /* Parity Error by UART */ #define UART_BUFFER_OVERFLOW 0x0200 /* receive ringbuffer overflow */ #define UART_NO_DATA 0x01ff /* no receive data available */ /* ** function prototypes */ /** @brief Initialize UART and set baudrate @param baudrate Specify baudrate using macro UART_BAUD_SELECT() @return none */ extern void uart_init(unsigned int baudrate); /** * @brief Get received byte from ringbuffer * * Returns in the lower byte the received character and in the * higher byte the last receive error. * UART_NO_DATA is returned when no data is available. * * @param void * @return lower byte: received byte from ringbuffer * @return higher byte: last receive status * - \b 0 successfully received data from UART * - \b UART_NO_DATA * <br>no receive data available * - \b UART_BUFFER_OVERFLOW * <br>Receive ringbuffer overflow. * We are not reading the receive buffer fast enough, * one or more received character have been dropped * - \b UART_OVERRUN_ERROR * <br>Overrun condition by UART. * A character already present in the UART UDR register was * not read by the interrupt handler before the next character arrived, * one or more received characters have been dropped. * - \b UART_FRAME_ERROR * <br>Framing Error by UART */ extern unsigned int uart_getc(void); extern uint8_t uart_getc_wait(uint8_t); extern void uart_flush (void); /** * @brief Put byte to ringbuffer for transmitting via UART * @param data byte to be transmitted * @return none */ extern void uart_putc(unsigned char data); /** * @brief Put string to ringbuffer for transmitting via UART * * The string is buffered by the uart library in a circular buffer * and one character at a time is transmitted to the UART using interrupts. * Blocks if it can not write the whole string into the circular buffer. * * @param s string to be transmitted * @return none */ extern void uart_puts(const char *s); extern void uart_puti_noasci(const uint16_t); /** * @brief Put string from program memory to ringbuffer for transmitting via UART. * * The string is buffered by the uart library in a circular buffer * and one character at a time is transmitted to the UART using interrupts. * Blocks if it can not write the whole string into the circular buffer. * * @param s program memory string to be transmitted * @return none * @see uart_puts_P */ extern void uart_puts_p(const char *s ); /** * @brief Macro to automatically put a string constant into program memory */ #define uart_puts_P(__s) uart_puts_p(PSTR(__s)) /** @brief Initialize USART1 (only available on selected ATmegas) @see uart_init */ extern void uart1_init(unsigned int baudrate); /** @brief Get received byte of USART1 from ringbuffer. (only available on selected ATmega) @see uart_getc */ extern unsigned int uart1_getc(void); /** @brief Put byte to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_putc */ extern void uart1_putc(unsigned char data); /** @brief Put string to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts */ extern void uart1_puts(const char *s ); /** @brief Put string from program memory to ringbuffer for transmitting via USART1 (only available on selected ATmega) @see uart_puts_p */ extern void uart1_puts_p(const char *s ); /** @brief Macro to automatically put a string constant into program memory */ #define uart1_puts_P(__s) uart1_puts_p(PSTR(__s)) /**@}*/ void usart_write_P (const char *Buffer,...); #define printf(format, args...) usart_write_P(PSTR(format), ## args); #endif // UART_H