Laboratorium Systemów wbudowanych Ćwiczenie nr l Podstawy
Transkrypt
Laboratorium Systemów wbudowanych Ćwiczenie nr l Podstawy
Laboratorium Systemów wbudowanych Wyższa Szkoła Zarządzania i Bankowości, Informatyka studia inżynierskie Ćwiczenie nr l Podstawy programowania mikrokontrolerów rodziny AVR8 opracował dr inż. Wojciech Zaborowski Plan ćwiczenia: Ćwiczenie wykonywane jest z wykorzystaniem zestawu uruchomieniowego ZL15AVR firmy Kamami. Zestaw uruchomieniowy zbudowany jest w oparciu o mikrokontroler ATMEL Atmega32. Szczegółowe informacje na temat budowy zestawu można uzyskać z jego dokumentacji (http://www.kamami.pl/dl/zl15avr.pdf). Do programowania mikrokontrolera wykorzystany zostanie pakiet oprogramowania AVR Studio 4 wraz z pakietem WinAVR. Połączenie tych dwóch pakietów pozwala w prosty sposób programować mikrokontrolery rodziny AVR z poziomu języka C z wykorzystaniem graficznego interfejsu użytkownika. Zestaw jest zasilany z portu USB komputera. Dodatkowo do programowania mikrokontrolera wykorzystuje się dedykowany programator z interfejsem JTAG (ZL15PRG) podłączony do drugiego portu USB. 1 Zadanie 1 Uruchomić środowisko AVR Studio 4. Skopiować i rozpakować na lokalny dysk projekt o nazwie LED. Przy pomocy polecenia Project→Open Project wczytać projekt (wczytać plik o nazwie led.aps). W pliku źródłowym led.c w sekcji komentarza opatrzonej słowem DESCRIPTIONS znajduje się opis połączeń, jakie należy wykonać przy pomocy dostępnych przewodów. Wykonanie wymienionych połączeń jest niezbędne do poprawnego uruchomienia przykładu i zaobserwowania efektów jego działania. UWAGA !!! – Wszelkie połączenia pomiędzy urządzeniami peryferyjnymi a mikrokontrolerem mogą być dokonywane wyłącznie przy odłączonym zasilaniu. Po wykonaniu połączeń opisanych w sekcji DESCRIPTION należy poprosić osobę prowadzącą zajęcia o sprawdzenie poprawności ich wykonania. Dopiero po uzyskaniu zgody można włączyć zasilanie zestawu. Aby stworzyć pliki niezbędne do zaprogramowania mikrokontrolera, należy przeprowadzić kompilację projektu. Wykonuje się to poleceniem Build→Build lub z wykorzystaniem klawisza skrótu F7. Po poprawnej kompilacji projektu można przystąpić do programowania wewnętrznej pamięci FLASH mikrokontrolera. Jeśli jest to pierwsza próba programowania, należy wcześniej przeprowadzić konfigurację programatora/debugera. Dokonuje się tego przy pomocy polecenia Laboratorium Systemów Wbudowanych – Wyższa Szkoła Zarządzania i Bankowości w Krakowie Tools→Program AVR→Connect… Wybranie tego polecenia powoduje pojawienie się okna wyboru przedstawionego na Rys. 1. (Uwaga – w niektórych sytuacjach poprawne skonfigurowanie programatora może wymagać uprawnień administratora na danym komputerze – w takiej sytuacji należy się zwrócić o pomoc do prowadzącego zajęcia ) Rys. 1 Okno konfiguracji programatora Z listy programatorów znajdujących się w oknie po lewej stronie należy wybrać JTAG ICE. Port komunikacyjny pozostawiamy na Auto, lub jeśli było wybrane inne ustawienie wybieramy Auto. Następnie wciskamy przycisk Connect… . Jeśli połączenia między komputerem, programatorem oraz zestawem uruchomieniowym funkcjonują poprawnie i konfiguracja przebiegła prawidłowo na ekranie pojawi się następujące okno: Rys. 2 Okno programatora w trybie JTAG Najważniejsze opcje i polecenia znajdują się na zakładce Program. Przycisk Erase Device powoduje wykasowanie wewnętrznej pamięci FLASH mikrokontrolera (co jest równoznaczne z usunięciem zapisanego w niej programu). 2 Laboratorium Systemów Wbudowanych – Wyższa Szkoła Zarządzania i Bankowości w Krakowie Do zaprogramowania tej pamięci wykorzystywać będziemy sekcję Flash. Powinna w niej być zaznaczona opcja Input HEX File (jak na Rys. 2). W polu obok należy wskazać plik, którym ma zostać zaprogramowana pamięć FLASH. Zwykle taki plik wynikowy posiada nazwę taką jak nazwa projektu, rozszerzenie .hex . Kompilator tworzy ten plik w podkatalogu ./default znajdującym się w katalogu z plikami projektu. Przed programowaniem należy zwrócić uwagę czy wskazany jest właściwy plik stanowiący rezultat kompilacji projektu nad którym aktualnie pracujemy, a nie przypadkowy plik mogący być pozostałością po pracy innych grup. Po wciśnięciu przycisku Program pamięć FLASH jest zapisywana zawartością pliku .hex i następuje automatyczne uruchomienie wczytanego programu, co w przypadku projektu led powinno być widoczne w postaci zapalających się i gasnących diod świecących D0-D7. Po prawidłowym wykonaniu wszystkich etapów związanych z uruchomieniem przy kładowego projektu o nazwie led dokonać modyfikacje w programie tak aby uzyskać efekt wędrującego światła (zapalamy diodę D0, w kolejnym kroku zapalamy diodę D1 i gasimy D0, w kolejnym zapalamy D2 i gasimy D1 itd. gdy zapalimy diodę D7 w kolejnym kroku zapalamy D6 i gasimy D7 itd. aż dojdziemy do diody D0. 2 Zadanie 2 – obsługa wejść i wyjść binarnych Punktem wyjścia będzie projekt o nazwie buzzer. W pierwszej kolejności należy rozpakować pliki umieszczone w archiwum buzzer.zip. Następnie wykonać niezbędne połączenia i zaprogramować mikrokontroler. Wykonać zestaw eksperymentów pozwalający określić w jaki sposób kontroluje się wysokość i czas trwania generowanych dźwięków. Odłączyć zasilanie. Wykonać dodatkowe połączenia Podłączyć wyjścia czteroprzyciskowej klawiatury SW0÷SW3 znajdujące się na złączu Con19 do wyprowadzeń portu PB0÷PB3 mikrokontrolera (Con16) w następujący sposób: SW0→PB0, SW1→PB1, SW2→PB2, SW3→PB3. Rozbudować projekt buzzer aby w zależności od wciśniętego przycisku generowany był dźwięk o różnych parametrach. Z punktu widzenia mikrokontrolera działanie przycisków SW0-SW3 jest następujące: • gdy przycisk nie jest wciśnięty, na linię portu, do której przycisk jest podłączony podawany jest stan wysoki (mikrokontroler „widzi” tą linie jako 1). • gdy przycisk jest wciśnięty, na linię portu do której jest podłączony podawany jest stan niski (mikrokontroler „widzi” tą linie jako 0). Zestaw przydatnych wiadomości na temat programowania mikrokontrolerów rodziny AVR8 z użyciem kompilatora AVR-GCC (wykorzystywanego w pakiecie AVR Studio 4) można znaleźć pod adresem http://hobby.abxyz.bplaced.net/index.php?pid=4&aid=2. Linie we/wy mikrokontrolera ATmega32 pogrupowane są w cztery ośmiobitowe porty A, B, C, D. Do obsługi tych portów wykorzystywane są trzy rejestry specjalne, oddzielne dla każdego portu: • rejestr kontroli kierunku portu DDRx, 3 Laboratorium Systemów Wbudowanych – Wyższa Szkoła Zarządzania i Bankowości w Krakowie • wykorzystywany już wcześniej rejestr wyjściowy PORTx • rejestr wejściowy PINx (za x należy wstawić odpowiednią nazwę portu. I tak dla Portu A mamy dedykowane rejestry PORTA, PINA, DDRA itp.). Pozwala to praktycznie dowolnie konfigurować poszczególne linie. Odczytywanie stanu poszczególnych linii portów wiąże się z manipulacjami na pojedynczych bitach. W związku z tym warto przypomnieć sobie w jaki sposób i z użyciem jakich operatorów języka C takie manipulacje można wykonywać. W języku C jest sześć operatorów bitowych:|,&,^,<<,>>,~. Zasadę ich działania najprościej jest objaśnić na przykładach. Liczby używane w przykładach przedstawione są w postaci dwójkowej. operator "|" - bitowa alternatywa lub inaczej suma logiczna (OR) 01010101 | 00110011 = 01110111 operator "&" - bitowa koniunkcja lub inaczej iloczyn logiczny (AND) 01010101 & 00110011 = 00010001 operator "^" - bitowa alternatywa wykluczająca (XOR) 01010101 ^ 00110011 = 01100110 operator "<<" - przesunięcie w lewo 1 0 0 1 1 0 0 1 << 3 = 1 1 0 0 1 0 0 0 (argument po "<<" określa o ile bitów należy przesunąć. Przy przesuwaniu o każdy bit, na najmniej znaczącej pozycji wpisywana jest wartość 0) operator ">>" - przesunięcie w prawo 1 0 0 1 1 0 0 1 >> 5 = 0 0 0 0 0 1 0 0 (argument po ">>" określa o ile bitów należy przesunąć. Przy przesuwaniu o każdy bit, na najbardziej znaczącej pozycji wpisywana jest wartość 0) operator "~" - dopełnienie jedynkowe lub inaczej negacja każdego bitu ~ 10011001 = 01100110 Aby móc odczytać stan przycisków SW0-3 podłączonych do linii PB0-PB3 mikrokontrolera musimy zacząć od odpowiedniego skonfigurowania portu PB. Wykonuje się to poprzez wpisanie do rejestru DDRB odpowiedniej wartości. Zasady konfiguracji linii portów są identyczne dla każdego z nich. Wpisanie do rejestru DDRx, na odpowiadającej danemu wyprowadzeniu pozycji bitowej wartości 1, konfiguruje tą linię jako wyjście, natomiast umieszczenie tam wartości 0 ustawia linię jako wejście. 4 Laboratorium Systemów Wbudowanych – Wyższa Szkoła Zarządzania i Bankowości w Krakowie (polecenie DDRB = 0x0F; konfiguruje cztery starsze linie – PB4-PB7 jako wejścia, a cztery młodsze linie – PB0-PB3 jako wyjścia). Odczyt stanu linii wejściowych portu wykonuje się poleceniem PINx : DDRB = 0x00; // konfiguracja wszystkich linii PB jako wejscia przyciski = PINB; // przypisanie zmiennej wynik aktualnego // linii portu PB stanu Jak wspomniano wcześniej, wciśnięcie przycisku powoduje, że na odpowiednim bicie w rejestrze PINx jest ustawiana wartość 0. Aby zatem stwierdzić fakt wciśnięcia któregokolwiek przycisku należy sprawdzić, które bity w momencie odczytu stanu portu B miały wartość 0 (powiedzmy, ze będziemy rozważać wciśnięcie przycisku S2 podłączonego do linii PB2). Pierwszym krokiem jest odrzucenie zbędnych informacji o stanie pozostałych linii portu. Najczęściej stosowanym rozwiązaniem jest tu wyzerowanie wszystkich bitów z wyjątkiem tego, który nas interesuje (w rozważanym przykładzie interesuje nas stan linii PB2 odwzorowywany na drugim bicie wartości odczytanej z portu B – dla przypomnienia bity w bajcie numerujemy od 0). Wyzerowania bitów dokonuje się poprzez operację iloczynu logicznego (operator &) na odczytanej poleceniem PINB wartości z tzw. maską. W rozważanym przypadku maska posiada wyłącznie jeden bit o wartości 1 na pozycji, która ma pozostać nie zmieniona. Na pozostałych pozycjach bitowych umieszczone są zera. Zatem dla sprawdzenia stanu linii PB2 maska będzie miała wartość 0b00000100 lub 0x04 w zapisie szesnastkowym. Stan przycisku S2 podłączonego do portu PB2 można zatem ustalić, jako wynik następującej operacji: przycisk_s2 = przyciski & 0b00000100; //w zm. przyciski // przechowywany jest stan portu B odczytany wcześniej // poleceniem PINB jeśli zmienna przycisk_s2 przyjmie wartość 0 oznaczać to będzie, że bit 2 w rejestrze PINB miał wartość 0 co prowadzi do wniosku, że przycisk S2 był wciśnięty. Jeśli natomiast wynik tej operacji będzie różny od zera oznacza to, że przycisk wciśnięty nie był. Aby nie marnować pamięci mikrokontrolera na deklaracje niepotrzebnych zmiennych, sprawdzenia zwykle dokonuje się za pomocą pojedynczej instrukcji if: if ( (przycisk_s2 & 0b00000100) == 0 ) { // tu będzie procedura obsługi naciśnięcia przycisku S2 } lub jeszcze prościej if (!((przyciski &0b00000100))) { // tu będzie procedura obsługi naciśnięcia przycisku S2 } 5 Laboratorium Systemów Wbudowanych – Wyższa Szkoła Zarządzania i Bankowości w Krakowie 3 Zadanie 3 – Ciekłokrystaliczny wyświetlacz znakowy Znakowy wyświetlacz LCD jest często stosowanym i stosunkowo prostym w obsłudze urządzeniem wyjściowym stosowanym w układach zbudowanych z wykorzystaniem różnych mikrokontrolerów jednoukładowych. Jedną z najbardziej popularnych konstrukcji są wyświetlacze oparte o kontroler zgodny HD44780. Kontrolery te posiadają możliwość sterowania wyświetlaczem ciekłokrystalicznym wyposażonym w pole odczytowe od 1x8 do 4x40 znaków. W minimalnej konfiguracji podłączenie wyświetlacza z mikrokontrolerem sterującym wykonywane jest przy użyciu 6 lub 7 linii we/wy. Przeanalizować i uruchomić przykładowy projekt umieszczony archiwum char_lcd.zip. Zapoznać się ze sposobem wyświetlania różnych informacji tekstowych. 3.1 Definiowanie własnych znaków. LCD ma miejsce dla ośmiu znaków zdefiniowanych przez użytkownika. Znaki te posiadają kody o wartościach od 00H do 07H. Dane te są przechowywane w pamięci wyświetlacza, która nazywa się CGRAM. Przed użyciem wzorce znaków muszą być wysłane do wyświetlacza. Zwykle wykonywane jest to zaraz po jego inicjalizacji (wzorce znaków są tracone bezpowrotnie po wyłączeniu zasilania lub inicjalizacji wyświetlacza). Każdy zdefiniowany znak wymaga 8 bajtów danych. Ósmym bajtem jest zazwyczaj $00, ponieważ jest to miejsce przeznaczone dla linii kursora. Standardowa czcionka wyświetlacza ma 5 pikseli szerokości i 7 pikseli wysokości. Jeden rząd pikseli na samym dole jest zarezerwowany na podkreślający znak kursora. Kształt znaku jest taki jaki jest układ zer i jedynek w bicie danych. Jedynka zaświeca piksel, zero pozostawia piksel zgaszonym. Oto przykład znaku zdefiniowanego przez użytkownika: 6 Poniżej zamieszczono fragment programu prezentujący w jaki sposób definiuje się i wykorzystuje własne znaki. (wystarczy go umieścić w przykładowym projekcie wykorzystywanym w tej części ćwiczenia, zamieniając odpowiedni fragment kodu źródłowego). //------------------------------------// main program //------------------------------------uint8_t znak[] = {0, 10, 10, 0, 17, 14, 6, 0}; //wlasny znak - buzka int main(void) { char temp, i; LCD_Initialize(); LCD_ProgrammChar(0, znak); LCD_GoTo(0,0); LCD_WriteText("- Wlasne znaki -"); // wyswietlenie zdefiniowanego znaku LCD_GoTo(0,1); LCD_WriteData(0); while(1){} return 0; } Na podstawie analizy przykładu przedstawionego powyżej zaprojektować zestaw polskich znaków diakrytycznych, aby możliwe było poprawne wyświetlenie tekstu „żółwik”. Wersja z dnia 2011-10-27 09:57 7