Es gibt eine sehr schöne und unproblematische Bibliothek für den UART von Peter Fleury (http://homepage.hispeed.ch/peterfleury/avr-software.html > UART Library), wenn man den UART einfach nur benutzen möchte würde ich empfehlen diese zu verwenden.
UART
#include <avr/io.h>
#include <inttypes.h>
// Sollte schon im Makefile definiert sein.
// In dem Fall hier einfach löschen.
#define F_CPU 7372800UL
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
// USART initialisieren
void
uart_init(void)
{
// Baudrate einstellen (Normaler Modus)
UBRRH = (uint8_t) (UBRR_BAUD>>8);
UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
// oder einfacher:
// UBRR = UBRR_BAUD;
// Aktivieren von receiver und transmitter
UCSRB = (1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
int
main(void)
{
uint8_t buffer;
// USART initialisieren
uart_init();
while (1)
{
// Warten bis Daten empfangen wurden
while ( !(UCSRA & (1<<RXC)) )
;
// Empfangsregister auslesen
buffer = UDR;
// Warten bis der Sendepuffer frei ist
while ( !( UCSRA & (1<<UDRE)) )
;
// Daten in den Puffer schreiben und damit senden
UDR = buffer;
}
}
Verwenden des UART mit Interrupts
#include <avr/io.h>
#include <avr/interrupt.h>
// Sollte schon im Makefile definiert sein.
// In dem Fall hier einfach löschen.
#define F_CPU 7372800UL
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
void
uart_init(void)
{
// Baudrate einstellen (Normaler Modus)
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
// oder einfacher:
// UBRR = UBRR_BAUD;
// Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
UCSRB = (1<<RXCIE)|(1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
int
main(void)
{
// USART initialisieren
uart_init();
sei();
// Nichts tun. Die Interrupts erledigten den Rest
while (1)
;
}
// Interrupt wird ausgelöst sobald neue Daten im USART-Empfangspuffer liegen
ISR(USART_RXC_vect)
{
unsigned char buffer;
// Daten aus dem Puffer lesen ...
buffer = UDR;
// ... warten bis der Sendepuffer leer ist ...
while ( !( UCSRA & (1<<UDRE)) )
;
// ... und gleich wieder zurück schicken
UDR = buffer;
}
Strings aus dem Flashspeicher ausgeben
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
// Sollte schon im Makefile definiert sein.
// In dem Fall hier einfach löschen.
#define F_CPU 7372800UL
#define BAUD 19200UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
// Für die bessere Lesbarkeit
#define TRUE 1
#define FALSE 0
volatile unsigned char daten_gesendet = TRUE;
const prog_char* volatile p_string;
// Zeichenkette im Flashspeicher
prog_char daten[] = "Hello World!\n";
// USART initialisieren
void
uart_init(void)
{
// Baudrate einstellen ( Normaler Modus )
UBRRH = (unsigned char) (UBRR_BAUD>>8);
UBRRL = (unsigned char) (UBRR_BAUD & 0x0ff);
// oder einfacher:
// UBRR = UBRR_BAUD;
// Aktivieren des Empfängers, des Senders und des "Daten empfangen"-Interrupts
UCSRB = (1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
int
main(void)
{
// USART initialisieren
uart_init();
sei();
while (1)
{
if (daten_gesendet)
{
// Flag zurücksetzen
daten_gesendet = FALSE;
// Pointer zeigt auf die Daten im Flashspeicher
p_string = daten;
/* Interrupt aktivieren, damit wird sofort zur
Interruptroutine gesprungen und das erste Zeichen gesendet. */
UCSRB |= (1<<UDRIE);
}
}
}
// Interrupt wird ausgelöst sobald der Sendepuffer leer ist
ISR(USART_UDRE_vect)
{
char buffer = pgm_read_byte(p_string++);
/* Wenn nicht das Ende der Zeichenkette erreicht wurde,
dann weiteres Zeichen senden */
if ( buffer != '\0' ) {
UDR = buffer;
} else {
// Flag setzen, das der String gesendet wurde
daten_gesendet = TRUE;
// Interrupt deaktivieren
UCSRB &= ~(1<<UDRIE);
}
}
Zum Anfang
Kommentare
# Jürgen Focke meinte am 12. Januar 2007, 23:47 dazu:
Hallo
ich arbeite mich derzeit in die Programmierung des Atmel Mega8 Controllers ein. Von früheren Projekten her kenne ich den Aufwand, den es kostet, in die elementaren Initialisierungen der Peripherie einzusteigen. Daher finde ich die gut dokumentierten Beispiele sehr hilfreich um eine Sammlung von Modulen zu bekommen, die ich in eigene Programme einbauen kann
Danke
Jürgen
# Thomas Schrein meinte am 17. August 2007, 11:32 dazu:
Finde ich prima, Deine Beispiele: arbeite mich, nach langer Pause (Jahre) wieder in das Thema Mikros ein und werde mit Deinen Beispielen als erstes üben. Danke und Gruß Thomas
# Werner Quednau meinte am 24. November 2008, 01:11 dazu:
Diese Seite ist sehr gut !
Kurzer Aufbau, nur das Wesentliche wird vermittelt.
Die Beispiele funktionieren !
Sie zeigen ein hohes Niveau des Authors.
Die Seite hat mir eine weitere Nacht des Ausprobierens erspart.
Vielen Dank
Werner Quednau
# jpcolli meinte am 28. Januar 2009, 17:17 dazu:
Echt klasse.
Ich habe bei 0 angefangen und hab das hier gleich alles verstanden.
Vielen Dank
# ThoWaBu meinte am 3. August 2010, 22:18 dazu:
Ein bisschen Kritik bei :
“Verwenden des UART mit Interrupts”
Also eine Warteschleife in einem Interrupt würde ich jetzt nicht unbedingt online stellen…
# Fabian Greif meinte am 4. August 2010, 00:32 dazu:
Generell ist das richtig, allerdings kommt die Schleife hier nur im unwahrscheinlichen Fall zum tragen, dass gerade im Hauptprogramm Daten gesendet werden.
In dem Beispiel also gar nicht, man könnte sie also auch weglassen.
# Thomas meinte am 22. November 2010, 11:25 dazu:
Hallo, wollte das Stringbeispiel implementieren, beim compilieren mit AVR Studio nölt der Compiler: bei const prog_char* volatile p_string; meldet er: error: expected’,’,’;’,’=’befor ‘*’ token
wie können die Kollegen, die vorher gepostet haben das Beispiel problemlos compiliert haben?
Was muss ich ändern?
Gruß
Thomas
# Thomas meinte am 23. November 2010, 17:17 dazu:
Hallo, sorry für den Quark, den ich geschrieben habe! Ich hatte verzockt die #include avr/pgmspace einzufügen!! Erst denken, dann posten! Also: auch ich finde die Beispiele oben super. Und sie laufen!!
Vielen Dank
# Stefan meinte am 10. Mai 2011, 15:46 dazu:
Super Beispiele, aber bei den Interrupts sollte man nicht mehr SIGNAL sondern ISR verwenden. Ansonsten sehr gute Seite!
Gruß Stefan
# Fabian Greif meinte am 10. Mai 2011, 16:53 dazu:
Ja, und anstelle von SIG_UART_RECV sollte man UART_RX_vect verwenden. Gleiches bei SIG_UART_DATA. Die Beispiel sind schon mehrere Jahre alt, da gab es die neuen Namen noch nicht ;-)
Ist jetzt aber geändert.
Grüße Fabian
Deine Meinung: