(→Einen String senden) |
(→Ohne Interrupts) |
||
| Zeile 1: | Zeile 1: | ||
| − | = Ohne | + | = Ohne Interrupts = |
| + | |||
| + | Hier eine der einfachsten Möglichkeiten, den Harware-[[UART]] von [[AVR]] zu nutzen. Die Empfangs- und Sendefunktionen sind so kurz, daß sie am besten als inline-Funktionen definiert werden. Auf Zeichen bzw. Ereignisse zu warten bezeichnet man auch als "''polling''". | ||
| − | |||
== C-Datei == | == C-Datei == | ||
| − | Der USART wird Initialisiert als UART mit dem Datenformat 8N1 (8 Datenbits, kein Parity, 1 Stopbit). Teilweise haben die Register andere Namen, etwa wenn mehr als ein USART vorhanden ist. Dann Gibt es Register UBRR0L, UBRR1L, etc. | + | Der USART wird Initialisiert als UART mit dem Datenformat 8N1 (8 Datenbits, kein Parity, 1 Stopbit). |
| + | |||
| + | Teilweise haben die Register andere Namen, etwa wenn mehr als ein USART vorhanden ist. Dann Gibt es Register UBRR0L, UBRR1L, etc. | ||
<pre> | <pre> | ||
| − | |||
#include "uart.h" | #include "uart.h" | ||
| Zeile 15: | Zeile 17: | ||
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1); | uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1); | ||
| − | UBRRH = ( | + | UBRRH = (uint8_t) (ubrr>>8); |
| − | UBRRL = ( | + | UBRRL = (uint8_t) (ubrr); |
// UART Receiver und Transmitter anschalten | // UART Receiver und Transmitter anschalten | ||
| Zeile 26: | Zeile 28: | ||
do | do | ||
{ | { | ||
| − | + | uint8_t dummy; | |
(void) (dummy = UDR); | (void) (dummy = UDR); | ||
} | } | ||
| Zeile 37: | Zeile 39: | ||
Im Header <tt>uart.h</tt> werden die Funktionen veröffentlicht und stehen in anderen Modulen zur Verfügung: | Im Header <tt>uart.h</tt> werden die Funktionen veröffentlicht und stehen in anderen Modulen zur Verfügung: | ||
;<tt>extern void uart_init()</tt>: Initialisiert den UART und aktiviert Receiver und Transmitter. | ;<tt>extern void uart_init()</tt>: Initialisiert den UART und aktiviert Receiver und Transmitter. | ||
| − | ;<tt>static inline void uart_putc (const | + | ;<tt>static inline void uart_putc (const uint8_t c)</tt>: Sendet das Zeichen <tt>c</tt> über den UART. |
| − | ;<tt>static inline | + | ;<tt>static inline uint8_t uart_getc_wait()</tt>: Wartet bis zum nächsten Empfang bzw. liefert das empfangene Zeichen. |
;<tt>static inline int uart_getc_nowait()</tt>: Schaut nach, ob ein Zeichen empfangen wurde und liefert dieses gegebenenfalls als <tt>int</tt> zurück (Wertebereich ist 0...255). Wurde nichts empfangen, wird <tt>-1</tt> geliefert. | ;<tt>static inline int uart_getc_nowait()</tt>: Schaut nach, ob ein Zeichen empfangen wurde und liefert dieses gegebenenfalls als <tt>int</tt> zurück (Wertebereich ist 0...255). Wurde nichts empfangen, wird <tt>-1</tt> geliefert. | ||
Die Defines <tt>F_CPU</tt> und <tt>BAUDRATE</tt> geben die Taktrate des AVR sowie die Baudrate an. Dabei hat <tt>F_CPU</tt> nur rein informativen Character, es ''ändert'' die CPU-Frequenz nicht! Der Define für <tt>F_CPU</tt> kann man in die Quelle dazu schreiben, oder man gibt einen Wert per Kommandozeile/[[make|Makefile]] an mit <tt>-DF_CPU=...</tt> | Die Defines <tt>F_CPU</tt> und <tt>BAUDRATE</tt> geben die Taktrate des AVR sowie die Baudrate an. Dabei hat <tt>F_CPU</tt> nur rein informativen Character, es ''ändert'' die CPU-Frequenz nicht! Der Define für <tt>F_CPU</tt> kann man in die Quelle dazu schreiben, oder man gibt einen Wert per Kommandozeile/[[make|Makefile]] an mit <tt>-DF_CPU=...</tt> | ||
| Zeile 50: | Zeile 52: | ||
static inline void | static inline void | ||
| − | uart_putc (const | + | uart_putc (const uint8_t c) |
{ | { | ||
| + | // Warten, bis UDR bereit ist für einen neuen Wert | ||
while (!(UCSRA & (1 << UDRE))) | while (!(UCSRA & (1 << UDRE))) | ||
; | ; | ||
| − | + | ||
| + | // UDR schreiben startet die Übertragung | ||
UDR = c; | UDR = c; | ||
} | } | ||
| − | static inline | + | static inline uint8_t |
uart_getc_wait() | uart_getc_wait() | ||
{ | { | ||
| + | // Warten, bis etwas empfangen wird | ||
while (!(UCSRA & (1 << RXC))) | while (!(UCSRA & (1 << RXC))) | ||
; | ; | ||
| − | + | ||
| − | return | + | // Das empfangene Zeichen zurückliefern |
| + | return UDR; | ||
} | } | ||
| Zeile 70: | Zeile 76: | ||
uart_getc_nowait() | uart_getc_nowait() | ||
{ | { | ||
| + | // Liefer das empfangene Zeichen, falls etwas empfangen wurde; -1 sonst | ||
return (UCSRA & (1 << RXC)) ? (int) UDR : -1; | return (UCSRA & (1 << RXC)) ? (int) UDR : -1; | ||
} | } | ||
Version vom 3. März 2006, 09:20 Uhr
Inhaltsverzeichnis
Ohne Interrupts
Hier eine der einfachsten Möglichkeiten, den Harware-UART von AVR zu nutzen. Die Empfangs- und Sendefunktionen sind so kurz, daß sie am besten als inline-Funktionen definiert werden. Auf Zeichen bzw. Ereignisse zu warten bezeichnet man auch als "polling".
C-Datei
Der USART wird Initialisiert als UART mit dem Datenformat 8N1 (8 Datenbits, kein Parity, 1 Stopbit).
Teilweise haben die Register andere Namen, etwa wenn mehr als ein USART vorhanden ist. Dann Gibt es Register UBRR0L, UBRR1L, etc.
#include "uart.h"
#define BAUDRATE 38400
void uart_init()
{
uint16_t ubrr = (uint16_t) ((uint32_t) F_CPU/(16*BAUDRATE) - 1);
UBRRH = (uint8_t) (ubrr>>8);
UBRRL = (uint8_t) (ubrr);
// UART Receiver und Transmitter anschalten
// Data mode 8N1, asynchron
UCSRB = (1 << RXEN) | (1 << TXEN);
UCSRC = (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0);
// Flush Receive-Buffer
do
{
uint8_t dummy;
(void) (dummy = UDR);
}
while (UCSRA & (1 << RXC));
}
Benutzer-Schnittstelle und Header
Im Header uart.h werden die Funktionen veröffentlicht und stehen in anderen Modulen zur Verfügung:
- extern void uart_init()
- Initialisiert den UART und aktiviert Receiver und Transmitter.
- static inline void uart_putc (const uint8_t c)
- Sendet das Zeichen c über den UART.
- static inline uint8_t uart_getc_wait()
- Wartet bis zum nächsten Empfang bzw. liefert das empfangene Zeichen.
- static inline int uart_getc_nowait()
- Schaut nach, ob ein Zeichen empfangen wurde und liefert dieses gegebenenfalls als int zurück (Wertebereich ist 0...255). Wurde nichts empfangen, wird -1 geliefert.
Die Defines F_CPU und BAUDRATE geben die Taktrate des AVR sowie die Baudrate an. Dabei hat F_CPU nur rein informativen Character, es ändert die CPU-Frequenz nicht! Der Define für F_CPU kann man in die Quelle dazu schreiben, oder man gibt einen Wert per Kommandozeile/Makefile an mit -DF_CPU=...
#ifndef _UART_H_
#define _UART_H_
#include <avr/io.h>
extern void uart_init();
static inline void
uart_putc (const uint8_t c)
{
// Warten, bis UDR bereit ist für einen neuen Wert
while (!(UCSRA & (1 << UDRE)))
;
// UDR schreiben startet die Übertragung
UDR = c;
}
static inline uint8_t
uart_getc_wait()
{
// Warten, bis etwas empfangen wird
while (!(UCSRA & (1 << RXC)))
;
// Das empfangene Zeichen zurückliefern
return UDR;
}
static inline int
uart_getc_nowait()
{
// Liefer das empfangene Zeichen, falls etwas empfangen wurde; -1 sonst
return (UCSRA & (1 << RXC)) ? (int) UDR : -1;
}
#endif /* _UART_H_ */
Mit Receive-Interrupt
Weitere Routinen
Einen String senden
Übergeben wird die Start-Adresse des Strings. Die Zeichenkette wird solange durchlaufen und die Zeichen ausgegeben, bis eine '\0' (Stringende-Marke) gelesen wird.
#include "uart.h"
void uart_puts (const char *s)
{
do
{
uart_putc (*s);
}
while (*s++)
}
// Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will
// Winwows: "\r\n"
// Linux : "\n"
// MacOS : "\r"
char text[] = "Hallo Welt.\r\n";
int main()
{
uart_init();
uart_puts (text);
uart_puts ("Hallo Welt!\r\n");
return 0;
}
Einen konstanten String senden
Unveränderliche Strings brauchen kein Platz im SRAM zu verschwenden, man lässt sie im Flash (wo sie sonst ebenfalls stehen für die SRAM-Initialisierung).
#include <avr/pgmspace.h>
#include "uart.h"
void uart_puts_P (PGM_P s)
{
while (1)
{
unsigned char c = pgm_read_byte (s);
s++;
if ('\0' == c)
break;
uart_putc (c);
}
}
// Ein Zeilenumbruch, abhängig davon, was die Gegenstelle haben will
// Winwows: "\r\n"
// Linux : "\n"
// MacOS : "\r"
const prog_char text_p[] = "Hallo Welt.\r\n";
int main()
{
uart_init();
uart_puts_P (text_p);
uart_puts_P (PSTR("Hallo Welt!\r\n"));
return 0;
}
Siehe auch
WebLinks