Instrukcja do ćwiczenia PE: Współpraca mikrokontrolera z klawiaturą
Transkrypt
Instrukcja do ćwiczenia PE: Współpraca mikrokontrolera z klawiaturą
Instrukcja do ćwiczenia: Współpraca mikrokontrolera z klawiaturą Materiał do samodzielnego opracowania: elementy języka C: typy danych i ich deklarowanie, operatory, instrukcje, pętle, funkcje – definiowanie, deklarowanie i wywoływanie, tablice i wskaźniki, pliki nagłówkowe, dyrektywy kompilatora: include, define. 1. Klawiatura W celu komunikacji z użytkownikiem, w układach wykorzystujących mikrokontrolery stosuje się klawiatury (rys. 1). Rys. 1. Klawiatura 16 przyciskowa [1]. Klawiatury są najczęściej zbudowane z łączników o działaniu chwilowym (przycisków), zwierających 2 styki. Na wejścia mikrokontrolera podaje się napięcie 0 V lub 5V w zależności od stanu styków łącznika (rys. 2). Rys. 2. Sposób podłączenia 4 przycisków do mikrokontrolera 2 Oporniki R ograniczają prąd płynący ze źródła zasilania przy zwartych stykach łącznika. Liczba łączników determinuje liczbę wejść mikrokontrolera, koniecznych do obsługi klawiatury. W przypadku dużej liczby klawiszy (powyżej kilku) stosuje się tzw. klawiaturę matrycową. Poszczególne łączniki zwierają linie zwane wierszami z liniami zwanymi kolumnami. Zarówno wiersze jak i kolumny są podłączone do wyprowadzeń mikrokontrolera. Tym sposobem ilość wyprowadzeń mikrokontrolera koniecznych do obsługi klawiatury jest mniejsza od liczby klawiszy (rys. 3). Rys. 3. Obsługa klawiatury matrycowej 2. Odczyt danych z wejść mikrokontrolera W celu umożliwienia odczytu zmiany stanu łącznika klawiatury konieczne jest skonfigurowanie wybranych wyprowadzeń mikrokontrolera jako wejść. Do rejestru DDRX należy wpisać stan 0 (X = {A, B, C, D}) [2]. Np. zapisanie do 5 bitu rejestru DDRA zera logicznego konfiguruje wyprowadzenie mikrokontrolera PA5 jako wejście. Na rys. 4 pokazano przykładowo składniki rejestru DDRA. Rys. 4. Składniki rejestru DDRA[3]. Rezystory R (20 … 50 kΩ) pokazane na rys. 2 i 3 (zwane podciągającymi) są wbudowane w mikrokontroler [3]. Ich uaktywnienie uzyskuje się poprzez wpisanie do odpowiedniego bitu (x) rejestru PORTx wartości logicznej jeden. Na rys. 5 pokazano poszczególne bity rejestru PORTA. Rys. 5. Składniki rejestru PORTA [3]. 3 Po skonfigurowaniu wyprowadzenia mikrokontrolera jako wejście, możliwy jest odczyt jego stanu logicznego w rejestrze PINX. Na rys. 6 pokazano przykładowo składniki rejestru PINA. Rys. 6. Składniki rejestru PINA [3]. Sterowanie funkcją i stanem logicznym wyprowadzeń mikrokontrolera w ramach pozostałych portów odbywa się analogicznie. Literę A w nazwie rejestru należy zamienić na B, C lub D. 3. Użyteczne funkcje języka C a) Wiadomości podstawowe W celu poprawienia przejrzystości programu za pomocą dyrektywy kompilatora „define” można nadać dowolnemu elementowi programu własną nazwę: #define zastępujący_ciąg_znaków zastępowany_ciąg_znaków np.: #define WEJSCIE_0 PB0 Zamiast odwoływać się w programie do małointuicyjnej nazwy PB0 oznaczającej 0 wyprowadzenie portu B, można stosować nazwę SEGMENT_A jednoznacznie określającej co jest sterowane z tego wyprowadzenia. Przy stosowaniu w programie funkcji generujących opóźnienie czasowe wymaga się podania kompilatorowi częstotliwości taktowania procesora. Służy do tego makro: #define F_CPU 16000000 Liczba występująca powyżej to częstotliwość rezonatora kwarcowego w [Hz]. Z praktyki programowania mikrokontrolerów wynika, że wszelkie konfiguracje części sprzętowej mikrokontrolera (wejścia, wyjścia, przetwornika A/C, itd.) powinny być umieszczone w oddzielnym pliku (tzw. nagłówkowym *.h) i dołączane w momencie kompilacji do właściwego pliku z tekstem programu. Owo dołączanie uzyskuje się stosując dyrektywę kompilatora: #include ”nazwa.pliku” Nazwa pliku obejmuje jego rozszerzenie (*.h). Do zapisywania w rejestrze zera lub jedynki logicznej służy makro _BV(...) [3]. Aby z niego skorzystać należy na początku programu dołączyć plik nagłówkowy io.h znajdujący się w katalogu z bibliotekami /avr: #include <avr/io.h> Ustawienie jedynki logicznej na wyprowadzeniu x portu X uzyskuje się za pomocą: PORTX |= _BV(PXx) Dla kilku wyprowadzeń jednocześnie instrukcja powinna wyglądać: 4 DDRX |= _BV(PXx1)|_BV(PXx2)|_BV(PXx3) gdzie: X = {A, B, C, D}, x = {0 … 7}, np. PORTB |= _BV(PB0) ustawia stan 1 na wyjściu 0 portu B. Stan niski ustawia się za pomocą instrukcji PORTX &= ~(_BV(PXx)) dla kilku wyprowadzeń jednocześnie: PORTX &= ~(_BV(PXx1)) & ~(_BV(PXx2)) & ~(_BV(PXx3)) Konfigurację wyprowadzenia x portu X jako wejścia uzyskuje się instrukcją: DDRX &= ~(_BV(PXx)) jako wyjścia: DDRX |= _BV(PXx) Odczyt stanu logicznego wejścia wykonuje się za pomocą makr: bit_is_clear(PINX,PXx) zwracającego wartość 1 jeżeli stan logiczny rejestru PINX, w polu x jest równy 0, oraz: bit_is_set(PINX,PXx) zwracającego wartość 1 jeżeli stan logiczny rejestru PINX, w polu x jest równy 1. Powyższe makra będą dostępne w programie po dołączeniu biblioteki io.h: #include <avr/io.h> Do odmierzania czasu i uzyskiwania opóźnienia czasowego przydatna jest funkcja: void _delay_ms(float liczba_ms) Aby z niej skorzystać należy dołączyć plik delay.h dyrektywą: #include <avr/delay.h> b) Odczyt danych z klawiatury matrycowej Do komunikacji z klawiaturą matrycową można wykorzystać funkcje z biblioteki RKlibAVR autorstwa Roberta Krzysztofa [4]. Do projektu należy dołączyć plik kbd.h dyrektywą: #include "kbd.h" 5 Ponadto należy dołączyć konfigurację części sprzętowej umieszczonej w pliku config.h: // linie kolumn klawiatury #define KBD_PORT_col1 #define KBD_BIT_col1 #define KBD_PORT_col2 #define KBD_BIT_col2 #define KBD_PORT_col3 #define KBD_BIT_col3 #define KBD_PORT_col4 #define KBD_BIT_col4 PORTX x PORTX x PORTX x PORTX x // linie wierszy klawiatury #define KBD_PORT_row1 #define KBD_BIT_row1 #define KBD_PORT_row2 #define KBD_BIT_row2 #define KBD_PORT_row3 #define KBD_BIT_row3 #define KBD_PORT_row4 #define KBD_BIT_row4 PORTX x PORTX x PORTX x PORTX x W pliku makefile należy umieścić następujący kod (zastępując całkowicie istniejący tekst): # Nazwa pliku z funkcją main() - BEZ ROZSZERZENIA! TARGET = nazwa_pliku_bez_rozszerzenia # Lista plików, których zmiana powoduje przebudowanie projektu CONFIG = config.h # Lista plików źródłowych w języku C SRC = $(TARGET).c # Lista plików źródłowych w asemblerze (rozszerzenie S - DUŻE S !) ASRC = # typ mikrokontrolera MCU = atmega32 # Format pliku wyjściowego (srec, ihex) FORMAT = ihex # Poziom optymalizacji (0, 1, 2, 3, s) # (Uwaga: 3 nie zawsze jest najlepszym wyborem) OPT = s # Katalog z bibliotekami użytkownika USRLIB = C:/WinAVR-20100110/lib # Lista plików źródłowych bibliotek w języku C SRCLIB = include $(USRLIB)/kbd/sources 6 include $(USRLIB)/delay/sources # Dodatkowe biblioteki # # Minimalna wersja printf #LDFLAGS += -Wl,-u,vfprintf -lprintf_min # # Zmiennoprzecinkowa wersja printf (wymaga biblioteki matematycznej) #LDFLAGS += -Wl,-u,vfprintf -lprintf_flt # # Biblioteka matematyczna #LDFLAGS += -lm include $(USRLIB)/avr_make Do inicjalizacji klawiatury matrycowej służy funkcja: void KBD_init (void) Odczyt kodu wciśniętego klawisza można uzyskać za pomocą funkcji: u08 KBD_read (void) gdzie: u08 liczba całkowita ośmiobitowa (0 do 28 – 1). Konwersję kodu klawisza na łańcuch znaków dla wyświetlacza LCD można uzyskać za pomocą funkcji: char* itoa (int wartosc, char *lancuch_zakow, int notacja) gdzie: wartosc – liczba do konwersji, *lancuch_zakow – liczba przekształcona na łańcuch znaków, notacja – system liczbowy (2, 8, 10, 16). Funkcja wymaga dołączenia do projektu biblioteki stdlib.h: #include <stdlib.h> c) Sterowanie wyświetlacza LCD Do sterowania wyświetlacza LCD zostaną wykorzystane funkcje z biblioteki tAvrLib autorstwa Tomasza Wasilczyka [5]. Biblioteka objęta jest licencją GNU LGPL v3. W folderze z zadaniem muszą być dostępne pliki hd44780.c, hd44780.h i macros.h – należy je skopiować z katalogu tAvrLib. Drugi z plików należy dołączyć do programu dyrektywą: #include "hd44780.h" W pliku zawierającym konfigurację części sprzętowej config.h należy umieścić następujący kod: // pod którym portem jest szyna danych #define HD44780_DATA_GPIO X //port wyświetlacza X = {A, B,C, D} // jaką część portu zajmuje szyna danych: // jeżeli wyświetlacz dołączono do wyprowadzeń portu 4 … 7 to Y = 1 // jeżeli wyświetlacz dołączono do wyprowadzeń portu 0 … 3 to Y = 0 #define HD44780_DATA_HIGHHALFBYTE Y 7 //Do jakiego portu X i nr wyprowadzenia x podłączono linię RS wyświetlacza: #define HD44780_RS_GPIO X #define HD44780_RS_BIT x //j. w. ale llinia E wyświetlacza: #define HD44780_E1_GPIO X #define HD44780_E1_BIT x //parametry wyświetlacza w znakach #define HD44780_WIDTH 16 #define HD44780_HEIGHT 2 Plik konfiguracyjny config.h powinien być dołączony w programie (#include...) wcześniej niż plik hd44780.h. Inicjalizacji wyświetlacza dokonuje się na początku programu za pomocą funkcji: void hd44780_init(void) Kasowanie znaków z wyświetlacza umożliwia funkcja: void hd44780_clear (void) Wyświetlenie znaków na konkretnym polu wyświetlacza umożliwia funkcja: void hd44780_goto (uint8_t x, uint8_t y) gdzie: x - żądana kolumna, y - żądany wiersz, uint8_t – liczba całkowita bez znaku (typ danej). Wyświetlenie ciągu znaków (łańcucha znaków zdefiniowanego jako tablica znaków) uzyskuje się dzięki funkcji: void hd44780_putStr (char *str, uint8_t length) gdzie: *str – wskaźnik do tablicy znaków, lenght – ilość znaków do wyświetlenia. lenght = -1 funkcja wyświetla wszystkie znaki z tablicy. Jeżeli 4. Przebieg ćwiczenia W zestawie uruchomieniowym ZL3AVR wyprowadzenia klawiatury są dostępne na złączach JP23 i JP3. Pierwsze złącze obejmuje wyprowadzenia wierszy i kolumn (W1 … W4, K1 … K4). Klawiatura, składająca się z 16 przycisków (S1 … S16) znajduje się w prawej dolnej części zestawu. Za pomocą złącza JP3 można ograniczyć liczbę klawiszy do 4 (S1, S5, S9, S13) zwierając po jednym styku każdego z przycisków do masy (GND). Klawiatura nie ma wbudowanych rezystorów podciągających, należy je uaktywnić na wejściach mikrokontrolera. Przykładowe zadania do wykonania: a) Napisać i uruchomić program, w którym naciśniecie przycisku spowoduje zaświecenie diody LED. b) Napisać i uruchomić program, w którym naciśniecie przycisku spowoduje zgaszenie diody LED. c) Napisać i uruchomić program, w którym cztery przyciski sterują dwiema diodami LED (włącz / wyłącz). 8 d) Napisać i uruchomić program, który spowoduje wypisanie na wyświetlaczu LCD kodu klawisza klawiatury matrycowej. W p. c należy wykorzystać wyświetlacz LCD znajdujący się w prawej, górnej części zestawu ZL3AVR. Jego wyprowadzenia są dostępne na złączu JP29 (LCD4bit). Wyprowadzenia złącza JP29 należy podłączyć do wyprowadzeń wybranego portu mikrokontrolera. Następnie należy poinformować kompilator o dokonanym wyborze wpisując odpowiednie ustawienia w pliku z konfiguracją sprzętową (patrz p. 3 c)). Potencjometr PR1 służy do regulacji kontrastu wyświetlacza. 5. Literatura [1] http://www.adatronik.com.pl/klawiatura4x4.jpg [2] „8-bit Microcontroller with 32K Bytes In-System Programmable Flash Atmega32 Atmega32L”, 2503O–AVR–07/09, www.atmel.com, [3] „avr-libc 1.6.7”, Generated by Doxygen 1.5.6 Wed Jan 6 12:08:48 2010, c:\Winavr-20100110\doc\avr-libc\, [4] R. Krzysztof, Dokumentacja biblioteki RKlibAVR, http://www.isaa.pl/download/doc_details/89-rklibavr-uniwersalna-biblioteka-dla-avr-gcc. [5] T. Wasilczyk, Dokumentacja biblioteki tAvrLib, http://tAvrLib.wasilczyk.pl. Wersja z dn. 22.02.2011 r.