Obsługa portu szeregowego w mikrokontrolerach AVR – rozwiązanie uniwersalne
Jakiś czas temu opisałem podstawy obsługi portu szeregowego w mikrokontrolerach AVR. W tym wpisie chciałbym przedstawić rozwiązanie bardziej uniwersalne (współpracuje z większością mikrokontrolerów AVR). Prezentowany projekt pozwala sprowadzić obsługę modułu UART do wybrania prędkości pracy i wywoływania instrukcji wyślij / odbierz.
Autorem prezentowanego rozwiązania jest Peter Fleury, zachęcam do odwiedzenia jego strony domowej http://homepage.hispeed.ch/peterfleury/. Znajdziesz tam kilka ciekawych projektów związanych z mikrokontrolerami AVR, opisy sprzętu i oprogramowania.
Biblioteka UART
Opisywany projekt, do obsługi portu UART wykorzystuje przerwania. Odbierane dane trafiają do bufora cyklicznego, skąd następnie mogą być odczytane za pomocą udostępnionej funkcji. Dzięki temu, nie musimy się martwić, że nie zdążymy odebrać jakiejś danej zanim pojawi się następna (oczywiście, jeśli bufor cykliczny nie zostanie przepełniony). Podobnie wygląda wysyłanie danych: najpierw zapisywane są one do bufora cyklicznego (za pomocą jednej z funkcji do tego służących), a następnie wysyłane w przerwaniach.
Funkcje biblioteki udostępniają także możliwość sprawdzenia statusu transmisji, tzn. czy podczas transmisji wystąpił błąd, a jeśli tak, to jakiego typu.
Przykład
Obsługa biblioteki jest naprawdę prosta. Spójrz na poniższy przykład – działa on na każdym mikrokontrolerze AVR z wbudowanym portem UART.
#include <stdlib.h> #include <avr/io.h> #include <avr/interrupt.h> #include <avr/signal.h> #include <avr/pgmspace.h> #include "uart.h" // częstotliwość CPU w MHz #ifndef F_CPU #define F_CPU 4000000UL #endif // prędkość transmisji 9600 #define UART_BAUD_RATE 9600 int main(void) { unsigned int c; // włączenie modułu UART, ustawienie prędkości transmisji uart_init(UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU)); // odblokowanie przerwań (transmisja obsługiwana jest w przerwaniach) sei(); // wysłanie ciągu znaków uart_puts("Ciąg przechowywany w pamięci SRAM\n"); // wysłanie ciągu znaków z pamięci programu uart_puts_P("Ciąg przechowywany w pamięci FLASH\n"); // wysłanie pojedynczego znaku uart_putc('\r'); for(;;) { // odczyt znaku z bufora cyklicznego // funkcja uart_getc() zwraca wynik 16-bitowy // młodszy bajt zawiera odebrany znak // starszy bajt przechowuje kod ostatniego błędu // UART_NO_DATA oznacza, że żadne dane nie są dostępne c = uart_getc(); if(c & UART_NO_DATA) { // brak danych w buforze } else { // dane dostępne, sprawdzenie, czy nie było błędu if(c & UART_FRAME_ERROR) { // wykryto błąd ramki (np. brak bitu stopu) uart_puts_P("UART Frame Error: "); } if(c & UART_OVERRUN_ERROR) { // wykryto nadpisanie uart_puts_P("UART Overrun Error: "); } if(c & UART_BUFFER_OVERFLOW) { // wykryto całkowite zapełnienie bufora cyklicznego uart_puts_P("Buffer overflow error: "); } // odesłanie znaku uart_putc((unsigned char)c); } } }
Funkcje
Dokładny opis funkcji znajduje się w dołączonej do projektu dokumentacji. Tutaj pokażę tylko jakie funkcje są dostępne.
void uart_init(unsigned int baudrate)– włącza moduł UART i ustawia prędkość transmisji,unsigned int uart_getc(void)– odczytuje odebrany bajt z bufora cyklicznego,void uart_putc(unsigned char data)– umieszca bajt do wysłania w buforze cyklicznym,void uart_puts(const char *s)– umieszcza ciąg znaków do wysłania w buforze cyklicznym,void uart_puts_p(const char *s)- umieszcza ciąg znaków (z pamięci programu) do wysłania w buforze cyklicznym,void uart1_init(unsigned int baudrate)- włącza drugi moduł UART i ustawia prędkość transmisji (tylko wybrane układy ATMega),unsigned int uart1_getc(void)- odczytuje odebrany bajt z bufora cyklicznego (drugi moduł - tylko wybrane układy ATMega),void uart1_putc(unsigned char data)- umieszca bajt do wysłania w buforze cyklicznym (drugi moduł - tylko wybrane układy ATMega),void uart1_puts(const char *s)- umieszcza ciąg znaków do wysłania w buforze cyklicznym (drugi moduł - tylko wybrane układy ATMega),void uart1_puts_p(const char *s)- umieszcza ciąg znaków (z pamięci programu) do wysłania w buforze cyklicznym (drugi moduł - tylko wybrane układy ATMega).
Podsumowanie
Prezentowane rozwiązanie polecam każdemu, kto chce szybko uruchomić i rozpocząć pracę z modułem UART w mikrokontrolerach AVR. Istotną informacją jest także to, że biblioteka dostępna jest na licencji GNU General Public License – warto wiedzieć co z tego wynika.
Biblioteka dostępna jest pod adresem: http://homepage.hispeed.ch/peterfleury/uartlibrary.zip
A Ty jak obsługujesz port szeregowy w mikrokontrolerach? Stosujesz własne rozwiązania, czy korzystasz z jakiejś biblioteki?
