Wyjście Spis treści Poprzedni Następny
Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek Konsultacja: Wojciech Grodowski, mgr inż. Janusz Wałaszek |
©2015 mgr
Jerzy Wałaszek
|
Tematy pokrewne | Podrozdziały | |
(w budowie) |
Rejestr licznika APP004 – kostka do gry Podsumowanie |
Rejestr licznika |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Oprócz samego mikroprocesora kontroler wyposażony jest w dodatkowe układy, które ułatwiają sterowanie oraz tworzenie różnych aplikacji. Licznik jest układem zliczającym impulsy podawane na jego wejście zegarowe. Z licznikiem w postaci układu scalonego spotkaliśmy się już w rozdziale o generatorach (jeśli go pominąłeś, to wróć i przeczytaj dokładnie podane tam informacje). Wbrew pozorom licznik jest bardzo pożytecznym urządzeniem i ma mnóstwo zastosowań. Mikrokontroler ATTINY13 posiada w swoim wnętrzu tylko jeden licznik 8-mio bitowy (jego starsi bracia mają tych liczników więcej i mogą one być 16-to bitowe). Licznik czasem nazywamy timerem, co po angielsku oznacza układ odmierzający czas. W najprostszym przypadku dostęp do licznika uzyskujemy za pomocą rejestru sterującego TCCR0B (ang. Timer Counter Control Register 0 B) oraz rejestru licznika TCNT0 (ang. Timer CouNTer 0). Istnieją jeszcze dodatkowe rejestry. Omówimy je później. Stan licznika odczytujemy lub zapisujemy do rejestru TCNT0. Rejestr sterujący TCCR0B określa sposób pracy licznika:
Rejestr sterowania licznikiem TCCR0B Na początek omówimy znaczenie trzech ostatnich bitów rejestru sterującego. Bity CS02, CS01 i CS00 określają źródło impulsów, które będą zliczane przez licznik – CS = Clock Select, czyli wybór zegara. Trzy bity dają 8 różnych możliwości. W poniższej tabelce termin FCPU oznacza częstotliwość impulsów zegarowych, które taktują mikrokontroler. Zwykle jest to 1MHz, lecz częstotliwość ta może się zmienić przez odpowiednie skonfigurowanie mikrokontrolera (teraz nie zaprzątaj sobie tym głowy i przyjmij po prostu, że twój ATTINY13 jest taktowany zegarem o częstotliwości około 1MHz z wewnętrznego generatora). Sygnał zegarowy o częstotliwości FCPU trafia do tzw. prescalera, czyli dzielnika częstotliwości, który dzieli ją przez 8, 64, 256 i 1024. Wyjście prescalera może stać się źródłem impulsów zegarowych dla licznika.
Ustawiając odpowiednio bity CS02, CS01 i CS02 określamy szybkość pracy licznika. Ponieważ zlicza on niezależnie od procesora w mikrokontrolerze, wykorzystuje się go często do precyzyjnego odmierzania czasu (stąd pochodzi angielska nazwa timer, czyli licznik czasu, czasomierz). Możemy również zliczać impulsy zewnętrzne. W tym wypadku sygnał należy doprowadzić do linii PB2 i ustawić ją jako wejście danych. Wykonajmy kilka prostych ćwiczeń. Podłącz do płytki bazowej ATTINY13 płytkę aplikacyjną APP001. Ustaw zworki w położeniu górnym, aby do portów mikrokontrolera były podłączone wszystkie diody LED (jeśli nie masz płytki APP001, to zbuduj ją na płytce stykowej i połącz z płytka bazową za pomocą przewodów). Uruchom Eclipse i utwórz nowy projekt AVR dla ATTINY13. Licznik TCNT0
Powyższy program uruchamia licznik w trybie zliczania impulsów zegarowych z podziałem przez 1024. Następnie w pętli głównej mikrokontroler pobiera zawartość rejestru licznika TCNT0, przesuwa ją o 3 bity w prawo i wpisuje do rejestru PORTB. Przesunięcie o trzy bity powoduje, że na diody LED płytki APP001 zostają podane stany pięciu najstarszych bitów licznika. Gdy uruchomisz ten program, to zobaczysz, że tylko trzy najstarsze diody mrugają wystarczająco wolno, aby oko mogło to zobaczyć. Policzmy:
1000000 Hz : 1024 = 976,5625 Hz
Tyle wynosi częstotliwość impulsów zegarowych, które są podawane na wejście licznika i następnie zliczane przez niego. Z jaką częstotliwością mrugają poszczególne diody LED? Policzmy:
Jak widzisz, ostatnia dioda D4 mruga z częstotliwością ok 4Hz, czyli cztery razy na sekundę. Każda niższa dioda mruga z częstotliwością dwa razy większą od swojej poprzedniczki. Dla D1 jest to częstotliwość ponad 30 Hz, której oko ludzkie już nie rozpoznaje – na tej "wadzie" wzroku człowieka bazuje kino oraz telewizja: jeśli obrazy będą się zmieniały około 30 razy na sekundę, to oko zarejestruje to jako obraz ciągły i ruchomy. Kolejny program wykorzystuje licznik do odmierzania czasu. Licznik potrafi pracować w wielu różnych trybach. Najprostszym z nich jest tzw. tryb normalny (ang. normal mode). Tryb ten jest automatycznie ustawiany w czasie startu mikrokontrolera lub po resecie. W trybie normalnym licznik zlicza impulsy aż do osiągnięcia maksymalnej wartości 255 (binarnie 0b11111111). Następny impuls zegarowy powoduje wyzerowanie licznika (binarnie 0b00000000) oraz ustawienie znacznika TOV0 (ang. Timer/Counter Overflow Flag – znacznik przepełnienia licznika 0) w rejestrze TIFR0 (ang. Timer/Counter 0 Interrupt Flag Register – rejestr znaczników przerwań, o przerwaniach piszemy w kolejnym rozdziale).
Rejestr TIFR0 Uwaga: znacznik TOV0 zerujemy zapisując do bitu nr 1 wartość 1, nie 0! Podłącz do płytki bazowej płytkę APP001 i ustaw zworki w położenie górne. Skompiluj w Eclipse poniższy program i prześlij go do kontrolera. Odmierzanie czasu – tryb normalny
Jak to działa? Źródłem impulsów zegarowych dla licznika jest tutaj preskaler ustawiony na dzielenie częstotliwości 1MHz przez 1024. Daje nam to częstotliwość około 976 Hz. Czyli w ciągu każdej sekundy do licznika trafia nieco ponad 976 impulsów zegara. Pojemność licznika jest zbyt mała, aby zliczyć tyle impulsów, ponieważ jest to licznik 8-mio bitowy. Jednakże załóżmy, że nie chcemy zliczać wszystkich impulsów w ciągu jednej sekundy, lecz jedynie 1/4 z nich. Daje nam to 976 / 4 = 244 impulsy. Tyle licznik może zliczyć. Aby się wyzerował po zliczeniu 244 impulsów (co odpowiada ok. 1/4 sekundy), musi mieć wartość początkową 11 (11 + 244 = 255 i następny impuls zeruje licznik). To dlatego wpisujemy tę wartość do rejestru licznika na początku programu. Następnie wywołujemy funkcję czekaj(), która w pętli sprawdza stan bitu TOV0 rejestru TIFR0. Gdy licznik się wyzeruje, bit TOV0 zostanie ustawiony na 1 i pętla while zostanie przerwana. Wtedy zerujemy bit TOV0 i do licznika ponownie wpisujemy 11. W programie musimy wywołać funkcję czekaj() dwukrotnie, aby uzyskać opóźnienie 1/2 sekundy. Operując odpowiednio ustawieniami preskalera oraz wartościami początkowymi licznika, możemy otrzymać różne czasy opóźnień. Lepsze sposoby odmierzania czasu poznamy w następnym rozdziale, gdy będziemy omawiać przerwania. W programie wykorzystujemy nowy element języka C – funkcję. Funkcja jest fragmentem programu, który możemy wielokrotnie wywoływać z różnych miejsc. Przed pierwszym użyciem funkcja musi zostać zdefiniowana. Definicja wygląda następująco:
typ nazwa(parametry)
Inną metodą odmierzania czasu jest wykorzystanie trybu CTC (ang. Clear Timer on Compare match – Zerowanie Licznika przy zgodności porównania). Tryb pracy licznika (inny niż normalny) ustawiamy w rejestrze TCCR0A (ang. Timer/Counter Control Register A).
Rejestr TCCR0A Pierwsze cztery bity określają sposób pracy linii PB0 (zwanej tutaj OC0A) i PB1 (zwanej tutaj OC0B). Omówimy je później. Ostatnie dwa bity (wraz z bitem WGM02 z rejestru TCCR0B) określają tryb pracy modułu licznika. Aby włączyć tryb CTC, należy bit WGM02 wyzerować (w czasie startu lub po resecie bit ten jest automatycznie zerowany), a bity WGM01 i WGM00 ustawić odpowiednio na: 1 i 0. Tryb CTC wykorzystuje rejestr OCR0A (ang. Output Compare Register – rejestr porównawczy wyjścia). Wartość umieszczona w rejestrze OCR0A jest ciągle porównywana ze stanem licznika. Gdy licznik osiągnie tę wartość, to zostaje wyzerowany, a w rejestrze TIFR0 będzie ustawiony na 1 znacznik OCF0A. W ten sposób program wykrywa fakt wyzerowania licznika. Poniższy program wykorzystuje tryb CTC do odmierzania czasu. Działa identycznie jak poprzedni (prześledź komentarze). Odmierzanie czasu – tryb CTC
Następny program wykorzystuje licznik do losowania liczby losowej. Liczba losowa (ang. random number) jest liczbą z pewnego przedziału, lecz której wartości nie potrafimy przewidzieć, dopóki się nie pojawi. To tak jak w rzucie kostką. Dopóki nie rzucimy (zakładamy, że kostka nie jest oszukana), nie wiemy, ile wypadnie oczek. W jaki sposób losować liczbę losową? Bardzo prosto: uruchamiamy licznik w trybie zliczania zegara FCPU/8 (normalnie 125000Hz) i czekamy na naciśnięcie klawisza. Licznik działa tak szybko, że nikt nie jest w stanie nacisnąć klawisz przy określonym stanie licznika. Gdy klawisz zostanie zwolniony, odczytujemy stan licznika. Stan ten jest naszą liczbą losową.
Losowanie1
Losowanie2
W drugim przypadku generowany ciąg liczb nie jest przypadkowy, ponieważ mikroprocesor mikrokontrolera pracuje synchronicznie z licznikiem: oba są sterowane z tego samego źródła sygnałów zegarowych. Aby się o tym przekonać, wystarczy kilka razy nacisnąć klawisz RST i obserwować początek serii.
Źródłem sygnału zegarowego dla licznika może być zmieniający się stan linii PB2, która w tym przypadku nosi nazwę T0. Podłącz do płytki bazowej płytkę aplikacyjną APP001 i prześlij do mikrokontrolera poniższy program:
Program w pętli odczytuje stan linii PB0 i kopiuje go na linię PB2. Do linii PB0 podłączony jest przycisk na płytce APP001. Licznik jest tak skonfigurowany, że źródłem jego impulsów zegarowych jest linia BP2. Gdy stan tej linii zmieni się z niskiego na wysoki (co odpowiada zwolnieniu przycisku), licznik zliczy impuls i zwiększy swój stan o 1. Zobaczymy to na dwóch ostatnich diodach LED podłączonych do linii PB3 i PB4. Pojawią się tam dwa najmłodsze bity rejestru licznika TCNT0. Zmień w programie wartość wpisywaną do rejestru TCCR0B z 0b111 na 0b110. W tej konfiguracji licznik zlicza impuls zegarowy przy przejściu z 1 na 0. Tutaj programowo zmieniamy stan linii T0 (PB2). Jednakże linia ta może pracować jako wejście, do którego przesyłamy ciąg impulsów zegarowych z zewnętrznego źródła. W takim przypadku licznik będzie zliczał impulsy pojawiające się na linii T0.
|
APP004 – Kostka do gry |
|||||||||||||||||||||||||||||||||||||||||
Wykorzystując licznik, zaprojektujemy kolejną
płytkę aplikacyjną, która będzie symulowała kostkę do gry.
Kostka będzie zawierała 7 diod LED oraz jeden przycisk. Po
naciśnięciu przycisku program wylosuje liczbę od 1 do 6 i
przedstawi ją w postaci oczek na kostce. Diody LED połączymy w 4
grupy sterowane oddzielnymi liniami portów:
Linię PB0 zarezerwujemy dla przycisku. Schemat płytki aplikacyjnej APP004 z kostką jest następujący:
Utwórz nowy projekt Eagle. Na schemacie wykorzystaj elementy: frames A5L-LOC
(ramka)
supply1 GND x 3 (masa) pinhead PINHD-2X4 PINHD-2X4/90 x 1 (goldpiny kątowe męskie do połączenia z płytką bazową, element obróć o 180º i odbij lustrzanie) switch-omron 10-XX x 1 (przycisk W) rlc R-EU R-EU_0204/7 x 4 (oporniki) led LED LED3MM x 7 (diody LED) Elementy rozmieść odpowiednio na schemacie, połącz przewodami, nazwij i nadaj im wartości. Na podstawie schematu utwórz płytkę PCB:
Test płytki APP004
W tablicy cube zdefiniowane są stany portu B dla poszczególnych układów oczek kostki. Program najpierw czeka na naciśnięcie przycisku, po czym przesyła kolejno zawartość tablicy cube na port B. W efekcie na kostce pojawiają się kolejne układy oczek. Program pozwala przetestować poprawność montażu płytki APP004. Program kostki do gry
Po naciśnięciu przycisku na płytce APP004 zostaje wykonany "rzut" kostką, a następnie wyświetlany jest wynik. Jeśli w trakcie wyświetlania wyniku zostanie ponownie naciśniety przycisk, to wykonywany jest nowy rzut. Po upływie 3 sekund wynik na kostce zaczyna mrugać, po czym diody LED gasną (w celu oszczędzania energii). |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe