189 lines
3.5 KiB
C
189 lines
3.5 KiB
C
|
/* USART-Init beim ATmegaXX */
|
||
|
|
||
|
|
||
|
#include <avr/io.h>
|
||
|
#include <avr/interrupt.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "config.h"
|
||
|
#include "uart.h"
|
||
|
|
||
|
#ifdef ATMEGA128
|
||
|
#define UCSRB UCSR0B
|
||
|
#define UCSRC UCSR0C
|
||
|
#define UDR UDR0
|
||
|
#define UBRRH UBRR0H
|
||
|
#define UBRRL UBRR0L
|
||
|
#define URSEL UMSEL
|
||
|
#endif
|
||
|
|
||
|
|
||
|
#define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16L))
|
||
|
|
||
|
|
||
|
#ifdef UART_INTERRUPT
|
||
|
volatile static char rxbuf[UART_RXBUFSIZE];
|
||
|
volatile static char txbuf[UART_TXBUFSIZE];
|
||
|
volatile static char *volatile rxhead, *volatile rxtail;
|
||
|
volatile static char *volatile txhead, *volatile txtail;
|
||
|
|
||
|
|
||
|
SIGNAL(SIG_UART_DATA) {
|
||
|
#ifdef UART_LEDS
|
||
|
PORTC ^= 0x01;
|
||
|
#endif
|
||
|
|
||
|
if ( txhead == txtail ) {
|
||
|
UCSRB &= ~(1 << UDRIE); /* disable data register empty IRQ */
|
||
|
} else {
|
||
|
UDR = *txtail; /* schreibt das Zeichen x auf die Schnittstelle */
|
||
|
if (++txtail == (txbuf + UART_TXBUFSIZE)) txtail = txbuf;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
SIGNAL(SIG_UART_RECV) {
|
||
|
int diff;
|
||
|
|
||
|
#ifdef UART_LEDS
|
||
|
PORTC ^= 0x02;
|
||
|
#endif
|
||
|
|
||
|
/* buffer full? */
|
||
|
diff = rxhead - rxtail;
|
||
|
if ( diff < 0 ) diff += UART_RXBUFSIZE;
|
||
|
if (diff < UART_RXBUFSIZE -1) {
|
||
|
// buffer NOT full
|
||
|
*rxhead = UDR;
|
||
|
if (++rxhead == (rxbuf + UART_RXBUFSIZE)) rxhead = rxbuf;
|
||
|
} else {
|
||
|
UDR; //reads the buffer to clear the interrupt condition
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endif // UART_INTERRUPT
|
||
|
|
||
|
|
||
|
void uart_init() {
|
||
|
PORTD |= 0x01; //Pullup an RXD an
|
||
|
|
||
|
UCSRA = 0;
|
||
|
UCSRB |= (1<<TXEN); //UART TX einschalten
|
||
|
UCSRC |= (1<<URSEL)|(3<<UCSZ0); //Asynchron 8N1
|
||
|
|
||
|
UCSRB |= ( 1 << RXEN ); //Uart RX einschalten
|
||
|
|
||
|
// UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8);
|
||
|
// UBRRL=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU));
|
||
|
|
||
|
UBRRL = 8;
|
||
|
|
||
|
#ifdef UART_INTERRUPT
|
||
|
// init buffers
|
||
|
rxhead = rxtail = rxbuf;
|
||
|
txhead = txtail = txbuf;
|
||
|
|
||
|
// activate rx IRQ
|
||
|
UCSRB |= (1 << RXCIE);
|
||
|
#endif // UART_INTERRUPT
|
||
|
}
|
||
|
|
||
|
#ifdef UART_INTERRUPT
|
||
|
void uart_putc(char c) {
|
||
|
volatile int diff;
|
||
|
|
||
|
/* buffer full? */
|
||
|
do {
|
||
|
diff = txhead - txtail;
|
||
|
if ( diff < 0 ) diff += UART_TXBUFSIZE;
|
||
|
} while ( diff >= UART_TXBUFSIZE -1 );
|
||
|
|
||
|
cli();
|
||
|
*txhead = c;
|
||
|
if (++txhead == (txbuf + UART_TXBUFSIZE)) txhead = txbuf;
|
||
|
|
||
|
UCSRB |= (1 << UDRIE); /* enable data register empty IRQ */
|
||
|
sei();
|
||
|
}
|
||
|
#else // WITHOUT INTERRUPT
|
||
|
void uart_putc(char c) {
|
||
|
while (!(UCSRA & (1<<UDRE))); /* warten bis Senden moeglich */
|
||
|
UDR = c; /* schreibt das Zeichen x auf die Schnittstelle */
|
||
|
}
|
||
|
#endif // UART_INTERRUPT
|
||
|
|
||
|
|
||
|
void uart_putstr(char *str) {
|
||
|
while(*str) {
|
||
|
uart_putc(*str++);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void uart_putstr_P(PGM_P str) {
|
||
|
char tmp;
|
||
|
while((tmp = pgm_read_byte(str))) {
|
||
|
uart_putc(tmp);
|
||
|
str++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void uart_hexdump(char *buf, int len)
|
||
|
{
|
||
|
unsigned char x=0;
|
||
|
char sbuf[3];
|
||
|
|
||
|
while(len--){
|
||
|
itoa(*buf++, sbuf, 16);
|
||
|
if (sbuf[1] == 0) uart_putc(' ');
|
||
|
uart_putstr(sbuf);
|
||
|
uart_putc(' ');
|
||
|
if(++x == 16) {
|
||
|
uart_putstr_P(PSTR("\r\n"));
|
||
|
x = 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef UART_INTERRUPT
|
||
|
char uart_getc()
|
||
|
{
|
||
|
char val;
|
||
|
|
||
|
while(rxhead==rxtail) ;
|
||
|
|
||
|
val = *rxtail;
|
||
|
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
|
||
|
|
||
|
return val;
|
||
|
}
|
||
|
#else // WITHOUT INTERRUPT
|
||
|
char uart_getc()
|
||
|
{
|
||
|
while (!(UCSRA & (1<<RXC))); // warten bis Zeichen verfuegbar
|
||
|
return UDR; // Zeichen aus UDR zurueckgeben
|
||
|
}
|
||
|
#endif // UART_INTERRUPT
|
||
|
|
||
|
// returns 1 on success
|
||
|
#ifdef UART_INTERRUPT
|
||
|
char uart_getc_nb(char *c)
|
||
|
{
|
||
|
if (rxhead==rxtail) return 0;
|
||
|
|
||
|
*c = *rxtail;
|
||
|
if (++rxtail == (rxbuf + UART_RXBUFSIZE)) rxtail = rxbuf;
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
#else // WITHOUT INTERRUPT
|
||
|
char uart_getc_nb(char *c)
|
||
|
{
|
||
|
if (UCSRA & (1<<RXC)) { // Zeichen verfuegbar
|
||
|
*c = UDR;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
#endif // UART_INTERRUPT
|