Blame | Last modification | View Log | Download
/** Copyright (c) 2006-2007 by Roland Riegel <feedback@roland-riegel.de>** This file is free software; you can redistribute it and/or modify* it under the terms of the GNU General Public License version 2 as* published by the Free Software Foundation.*/#include <stdio.h>#include <avr/interrupt.h>#include <avr/io.h>#include <avr/pgmspace.h>#include <avr/sfr_defs.h>#include <avr/sleep.h>#include "uart.h"/* some mcus have multiple uarts */#ifdef UDR0#define UBRRH UBRR0H#define UBRRL UBRR0L#define UDR UDR0#define UCSRA UCSR0A#define UDRE UDRE0#define RXC RXC0#define UCSRB UCSR0B#define RXEN RXEN0#define TXEN TXEN0#define RXCIE RXCIE0#define UCSRC UCSR0C#define URSEL#define UCSZ0 UCSZ00#define UCSZ1 UCSZ01#define UCSRC_SELECT 0#else#define UCSRC_SELECT (1 << URSEL)#endif#ifndef USART_RXC_vect#if defined(UART0_RX_vect)#define USART_RXC_vect UART0_RX_vect#elif defined(UART_RX_vect)#define USART_RXC_vect UART_RX_vect#elif defined(USART0_RX_vect)#define USART_RXC_vect USART0_RX_vect#elif defined(USART_RX_vect)#define USART_RXC_vect USART_RX_vect#elif defined(USART0_RXC_vect)#define USART_RXC_vect USART0_RXC_vect#elif defined(USART_RXC_vect)#define USART_RXC_vect USART_RXC_vect#else#error "Uart receive complete interrupt not defined!"#endif#endif#define BAUD 9600UL#define UBRRVAL (F_CPU/(BAUD*16)-1)#define USE_SLEEP 1void uart_init(){/* set baud rate */UBRRH = UBRRVAL >> 8;UBRRL = UBRRVAL & 0xff;/* set frame format: 8 bit, no parity, 1 bit */UCSRC = UCSRC_SELECT | (1 << UCSZ1) | (1 << UCSZ0);/* enable serial receiver and transmitter */#if !USE_SLEEPUCSRB = (1 << RXEN) | (1 << TXEN);#elseUCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);#endif}void uart_putc(uint8_t c){if(c == '\n')uart_putc('\r');/* wait until transmit buffer is empty */while(!(UCSRA & (1 << UDRE)));/* send next byte */UDR = c;}void uart_putc_hex(uint8_t b){/* upper nibble */if((b >> 4) < 0x0a)uart_putc((b >> 4) + '0');elseuart_putc((b >> 4) - 0x0a + 'a');/* lower nibble */if((b & 0x0f) < 0x0a)uart_putc((b & 0x0f) + '0');elseuart_putc((b & 0x0f) - 0x0a + 'a');}void uart_putw_hex(uint16_t w){uart_putc_hex((uint8_t) (w >> 8));uart_putc_hex((uint8_t) (w & 0xff));}void uart_putdw_hex(uint32_t dw){uart_putw_hex((uint16_t) (dw >> 16));uart_putw_hex((uint16_t) (dw & 0xffff));}void uart_putw_dec(uint16_t w){uint16_t num = 10000;uint8_t started = 0;while(num > 0){uint8_t b = w / num;if(b > 0 || started || num == 1){uart_putc('0' + b);started = 1;}w -= b * num;num /= 10;}}void uart_putdw_dec(uint32_t dw){uint32_t num = 1000000000;uint8_t started = 0;while(num > 0){uint8_t b = dw / num;if(b > 0 || started || num == 1){uart_putc('0' + b);started = 1;}dw -= b * num;num /= 10;}}void uart_puts(const char* str){while(*str)uart_putc(*str++);}void uart_puts_p(PGM_P str){while(1){uint8_t b = pgm_read_byte_near(str++);if(!b)break;uart_putc(b);}}uint8_t uart_getc(){/* wait until receive buffer is full */#if USE_SLEEPuint8_t sreg = SREG;sei();while(!(UCSRA & (1 << RXC)))sleep_mode();SREG = sreg;#elsewhile(!(UCSRA & (1 << RXC)));#endifuint8_t b = UDR;if(b == '\r')b = '\n';return b;}EMPTY_INTERRUPT(USART_RXC_vect)