Prezentowane materiały są przeznaczone dla uczniów szkół ponadgimnazjalnych. Autor artykułu: mgr Jerzy Wałaszek, wersja1.0 Konsultacja: Wojciech Grodowski |
©2013 mgr
Jerzy Wałaszek
|
Licznik lub timer (czytaj: tajmer) jest rejestrem, który potrafi zliczać impulsy zegarowe. Z licznikami spotkaliśmy się już wcześniej. Mikrokontroler ATTINY13 zawiera jeden taki licznik, który ma 8 bitów pojemności. Dostęp do zawartości licznika odbywa się poprzez rejestr o nazwie TCNT0 (ang. Timer CouNTer 0). Zapis do rejestru TCNT0 powoduje odpowiednią zmianę zawartości licznika. Odczyt rejestru TCNT0 udostępnia aktualną zawartość licznika (czyli wartość, do której licznik doliczył).
Ponieważ licznik ten jest ośmiobitowy, to zlicza w zakresie od 0 do 255. W normalnym trybie pracy licznik przewija się na 0 po osiągnięciu wartości 255.
Oprócz rejestru TCNT0 mikrokontroler posiada kilka dodatkowych rejestrów, które sterują sposobem pracy tego licznika. Jednym z nich jest rejestr o nazwie TCCR0B (ang. Timer Counter Control Register 0 B). Poszczególne bity tego rejestru są następujące:
bit: | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
nazwa: | FOC0A | FOC0B | – | – | WGM02 | CS02 | CS01 | CS00 |
Dzisiaj będziemy wykorzystywać tylko trzy ostatnie bity oznaczone jako CS00, CS01 i CS02 (funkcje pozostałych bitów opiszemy w odpowiednim czasie w dalszej części kursu). Bity te 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). 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.
CS02 | CS01 | CS00 | Opis |
0 | 0 | 0 | Brak impulsów zegarowych, licznik jest zatrzymany. |
0 | 0 | 1 | Licznik zlicza impulsy o częstotliwości FCPU (1000000 Hz). |
0 | 1 | 0 | Licznik zlicza impulsy o częstotliwości FCPU/8 (125000 Hz) |
0 | 1 | 1 | Licznik zlicza impulsy o częstotliwości FCPU/64 (15625 Hz) |
1 | 0 | 0 | Licznik zlicza impulsy o częstotliwości FCPU/256 (3906,25 Hz) |
1 | 0 | 1 | Licznik zlicza impulsy o częstotliwości FCPU/1024 (976,5625 Hz) |
1 | 1 | 0 | Licznik zlicza impulsy z linii PB2 pracującej jako wejście T0. Zliczenie następuje przy opadającym zboczu impulsu. |
1 | 1 | 1 | Licznik zlicza impulsy z linii PB2 pracującej jako wejście T0. Zliczenie następuje przy narastającym zboczu impulsu. |
Ustawiając odpowiednio bity CS00...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.
Utworzymy prosty układ, który będzie nam pokazywał stan najstarszego bitu licznika. Licznik ustawimy, tak aby zliczał impulsy zegarowe z częstotliwością FCPU/1024. Najstarszy bit będzie się zmieniał z częstotliwością FCPU/1024/256 = 3,814697265625Hz, czyli około 4 razy na sekundę. Licznik będzie zliczał w kółko od 0 do 255.
|
|
Spis elementów:
Element | Ilość | Opis |
programator ISP | 1 | do zasilania i programowania mikrokontrolera |
płytka stykowa + kable | 1 | do montażu układu |
ATTINY13 | 1 | mikrokontroler |
opornik 220Ω/0,125W | 1 | –( )– do ograniczania napięcia i prądu diody LED |
kondensator 100nF | 1 | do eliminacji zakłóceń (nie musisz go koniecznie stosować, lecz jest to zalecane) |
czerwona dioda LED | 1 | do sygnalizacji stanu wysokiego na wyjściu PB0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
/* * ATTINY13_0012.c * * Created: 2014-06-09 19:35:00 * Author: Jerzy Wałaszek */ #include <avr/io.h> int main(void) { DDRB = (1<<PB0); // Ustawiamy linię PB0 jako wyjście TCCR0B = (1<<CS02)|(1<<CS00); // Uruchamiamy licznik z częstotliwością FCPU/1024 while(1) PORTB = (1<<PB5) | (TCNT0 >> 7); } |
SN7404LS |
|
|
Spis elementów:
Element | Ilość | Opis |
programator ISP | 1 | do zasilania i programowania mikrokontrolera |
płytka stykowa + kable | 1 | do montażu układu |
ATTINY13 | 1 | mikrokontroler |
SN7404LS | 1 | 6 inwerterów NOT do konstrukcji generatora |
opornik 470Ω/0,125W | 1 | –( )– do ograniczania napięcia i prądu diody LED na wyjściu generatora |
opornik 220Ω/0,125W | 4 | –( )– do ograniczania napięcia i prądu diody LED |
opornik 1kΩ/0,125W | 1 | –( )– do generatora impulsów |
kondensator 100nF | 1 | do eliminacji zakłóceń (nie musisz go koniecznie stosować, lecz jest to zalecane) |
kondensator 100µF/6,3V | 1 | do generatora impulsów |
czerwona dioda LED | 5 | do sygnalizacji stanu wysokiego na wyjściu generatora oraz wyjściach mikrokontrolera |
mikroprzełącznik | 1 | do przekazywania impulsów z generatora na wejście T0 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/* * ATTINY13_0013.c * * Created: 2014-06-10 07:36:00 * Author: Jerzy Wałaszek */ #include <avr/io.h> int main(void) { DDRB = (1<<PB4)|(1<<PB3)|(1<<PB1)|(1<<PB0); // Ustawiamy linie wyjściowe PORTB = (1<<PB5)|(1<<PB2); // Podłączamy oporniki podciągające i zerujemy wyjścia TCNT0 = 0; // Zerujemy licznik TCCR0B = (1<<CS02)|(1<<CS01)|(1<<CS00); // Licznik zlicza impulsy z PB2 przy narastającym zboczu while(1) PORTB = (1<<PB5)|(1<<PB2)|(TCNT0 & 0b0011)|((TCNT0 & 0b1100)<<1); // Licznik na wyjście } |
W generatorze zmień kondensator 100µF na 1000µF, co spowoduje zmniejszenie częstotliwości generowanych impulsów. Następnie zwróć uwagę, że stan licznika zmienia się wtedy, gdy dioda na wyjściu generatora zaczyna świecić, czyli gdy pojawia się na tym wyjściu stan logiczny 1. Licznik zlicza impulsy zewnętrzne przy narastającym zboczu (zmianie z 0 na 1) sygnału na wejściu T0 (PB2). Zmień teraz wiersz 15 na:
TCCR0B = (1<<CS02)|(1<<CS01);
Stan licznika zmienia się, gdy dioda LED gaśnie, czyli stan na wyjściu generatora zmienia się z 0 na 1. Licznik zlicza impulsy generatora przy opadającym zboczu sygnału.
Na pierwszy rzut oka może się wydawać, że projektu tego nie da się zrealizować, ponieważ do wyświetlania wyniku potrzebujemy 7 diod oraz 1 przycisku, co angażuje 8 linii portów, a my mamy do dyspozycji jedynie 5 linii PB0...PB4 (linię PB5/RESET zostawiamy w spokoju). Jeśli jednak dokładnie przyjrzysz się układom oczek, to zauważysz, że poszczególne oczka nie są niezależne, lecz tworzą cztery grupy:
Oczka 1 |
Grupy G1 |
Jeśli przyjmiemy prąd diody na poziomie 5 mA, to do jednego portu możemy podłączyć równolegle dwie diody LED, które będą zapalane stanem wysokim. Rozważania te prowadzą do następującego schematu:
|
|
Ponieważ kostka z diod LED jest dosyć trudna do odtworzenia na płytce stykowej, zaprojektowałem odpowiednią płytkę drukowaną:
Na powyższym rysunku jest widok płytki od strony ścieżek. Płytkę taką można utworzyć w dowolnym edytorze PCB, których mnóstwo znajdziesz w Internecie. Ja korzystałem z bardzo prostego edytora PCB Artist, ale może być dowolny inny. Kolorem zielonym zaznaczony jest obrys płytki. Kolor czerwony oznacza ścieżki. Kolor niebieski to połączenia przewodowe po drugiej stronie płytki. Kolor biały to punkty lutownicze elementów. Kolor żółty oznacza otwory przelotowe, w których lutujemy przewody (oznaczone na niebiesko) łączące ścieżki po drugiej stronie płytki.
Tworzenie płytek to temat na osobny kurs elektroniki. Poradniki możesz znaleźć w sieci. Ja stosuję następującą prostą metodę (wiem, że są lepsze, ale zwykle wymagają one wprawy lub sprzętu), która jeszcze mnie nie zawiodła:
Najpierw przygotowuję projekt płytki w edytorze PCB. Następnie drukuję na zwykłej kartce papieru same ścieżki oraz zarys płytki (wydruk musi być od strony ścieżek). Da się to zrobić bezpośrednio z edytora PCB.
Przygotowuję odpowiednią płytkę jednostronnie miedziowaną. Płytkę laminatową da się łatwo przyciąć nawet zwykłym nożem do tapet. Wystarczy kilkakrotnie przejechać nim wzdłuż linii cięcia po jednej i po drugiej stronie płytki, a następnie płytkę przełamujemy.
Rysunek płytki wycinam z zapasem około 2 cm i zawijam wokół płytki. Warstwa miedzi ma być od strony wydruku:
Za pomocą punktaka (coś z ostrym końcem) delikatnie nakłuwam każdy otwór wydrukowany na papierze. Powoduje to przeniesienie punktów otworów z papieru na warstwę miedzi. Operację tę należy przeprowadzać ostrożnie i z wyczuciem. Zbyt silne nakłucie spowoduje deformację warstwy miedzi wokół przyszłego otworu, a w konsekwencji odpadnięcie ścieżki, czego raczej należy unikać. Wytłoczone w miedzi punkty ułatwią wiercenie.
Otwory wiercimy małą wiertarką elektryczną (za około 30 zł do kupienia w każdym sklepie dla elektroników) i wiertłem 0,8mm. Należy zwrócić uwagę, aby wiertło było zawsze prowadzone prostopadle do powierzchni płytki. I nie rób tego na stole gościnnym, załatw sobie jakąś podkładkę, najlepiej deseczkę o grubości 2cm.
Po wywierceniu otworków papier usuwam. Płytkę myję bardzo dokładnie środkami do mycia naczyń (np. płyn Ludwik) i po wyschnięciu szlifuję bardzo drobnym papierem ściernym. Operacja ta ma na celu usunięcie z powierzchni płytki wszelkich zanieczyszczeń, tlenków i zadziorów po wierceniu.
Teraz najtrudniejsza część procesu. Za pomocą pisaka edding 141 F (taki zwykły, czarny, niezmywalny, 0,6mm) najpierw obrysowuję delikatnie wszystkie otwory kółeczkami, tak aby otwór znalazł się w środku. Kółeczka posłużą za punkty lutownicze.
Następnie kółeczka łączę liniami wg projektu płytki. Linie rysuję zwykle grubsze niż wynika to z projektu. Po prostu tak jest pewniej. Nie żałuję pisaka i każdą linię poprawiam po wyschnięciu pierwszej kreski. Nie rób tego, gdy tusz jest jeszcze mokry, ponieważ końcówka pisaka może go zdzierać i zostaną nieładne przerwy wewnątrz ścieżek. Najlepiej zrób rysunek, poczekaj 10-15 minut i popraw go jeszcze raz. W trakcie rysowania unikam dotykania płytki palcami. Płytkę najlepiej jest sobie jakoś umocować, co na pewno wpłynie na precyzję rysunku ścieżek. Jeśli na tym etapie wystąpi jakaś pomyłka, to pisak da się łatwo zmyć rozpuszczalnikiem nitro. Oczywiście rysowanie należy wtedy rozpocząć od początku.
Kolejnym etapem jest wytrawienie płytki. W sklepie elektronicznym kupujemy małą paczuszkę nadsiarczanu sodowego B327 (niektórzy trawią płytki chlorkiem żelaza – też można, lecz chlorek bardzo wszystko brudzi, a jeśli kapnie ci na spodnie, to będziesz miał dodatkowy wywietrznik). Wystarczy ci 100g tego środka na kilka płytek. Na opakowaniu jest dokładna instrukcja użytkowania. Proszek rozpuszczamy w gorącej wodzie o temperaturze około 50 stopni. Należy to zrobić w plastikowej kuwetce, aby rodzic żeński nie zrobił nam później awantury. Taką małą kuwetkę kupisz za grosze w supermarkecie. Trawienie rób w miejscu, gdzie nic nie uszkodzisz (kuchnia, balkon, piwnica, itp. zapewnij sobie dopływ powietrza).
Po rozpuszczeniu nadsiarczanu sodowego w wodzie wkładamy do kuwety płytkę i czekamy, aż zostanie wytrawiona na niej warstwa miedzi. Trwa to około 10...20min (w zależności od stężenia środka). Od czasu do czasu poruszaj delikatnie kuwetą. Płyn powinien zmieniać barwę na lekko niebieską, co jest dobrym objawem. Na powierzchni miedzi możesz zaobserwować małe bąbelki. Jeśli cię to ciekawi, to zapytaj swojego chemika o reakcję, jaka się odbywa w kuwecie.
Gdy cała miedź zostanie wytrawiona, wyjmij płytkę z kuwety (jeśli będziesz ją zbyt długo trawił, to mogą ci poznikać niektóre ścieżki), przepłukaj ją dokładnie w letniej wodzie i wysusz. Płyn trawiący wylej do ubikacji i spuść wodę. Kuwetę również umyj w letniej wodzie. Jeszcze ci się przyda.
Teraz należy dokładnie przyjrzeć się ścieżkom, czy nie mają przerw lub zwarć (w razie wątpliwości posłuż się miernikiem nastawionym na mierzenie oporności). Zwarte ścieżki łatwo rozłączysz małym skalpelem. Ubytki ścieżek trzeba będzie naprawić w czasie lutowania elementów za pomocą małego drucika. Pisak zmywasz łatwo rozpuszczalnikiem nitro.
Ja dodatkowo pokrywam ścieżki roztworem kalafonii w denaturacie. Tworzy to małą warstewkę ochronną i ułatwia później lutowanie. Roztwór taki bardzo łatwo przygotujesz: odlej do małego słoiczka trochę denaturatu i wrzuć do niego kawałek kalafonii. Po kilku minutach kalafonia się rozpuści.
Pozostaje nam jedynie wlutować w płytkę elementy. Przewody połączeniowe do płytki stykowej powinny być zakończone odpowiednimi wtykami. Gotowe przewody możesz kupić w sklepie elektronicznym lub na aukcji w serwisie Allegro.pl. Pamiętaj jednak, aby nie zostawiać ich "wiszących" na wlutowanym w płytkę drucie, ponieważ po kilku wygięciach drucik się po prostu złamie. Ja zawsze pokrywam miejsce styku przewodu z płytką klejem butapren, który doskonale się do tego nadaje – nie żałuj kleju, daj kilka warstw w odstępach co godzinę. Przemyśl zastosowanie obudowy na kostkę – wystarczy małe pudełeczko (najlepiej czarne) z otworkami na diody LED i przewody. Takie pudełko zabezpieczy płytkę przed przypadkowym kontaktem z metalowymi przedmiotami (zwarcie) oraz ukryje niedoróbki.
Płytkę zastosujemy w projekcie kostki elektronicznej. Kolejność połączeń jest następująca (od strony elementów):
GND PB1 PB2 PB3 PB4
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
/* * ATTINY13_0014.c * * Created: 2014-06-15 10:14:00 * Author: Jerzy Wałaszek */ #include <avr/io.h> #include <util/delay.h> int main(void) { unsigned char cube[] = {0b100011, // 1 oczko 0b100101, // 2 oczka 0b100111, // 3 oczka 0b101101, // 4 oczka 0b101111, // 5 oczek 0b111101, // 6 oczek 0b100101, // Obrót 1 0b110001, // Obrót 2 0b101001, // Obrót 3 0b100011}; // obrót 4 unsigned char i,v,c; DDRB = (1<<PB4)|(1<<PB3)|(1<<PB2)|(1<<PB1); // Ustawiamy linie wyjścia i wejścia PORTB = (1<<PB5)|(1<<PB0); // Do linii PB5 (RESET) i PB0 podpinamy oporniki podciągające TCCR0B = 5; // Licznik będzie zliczał z częstotliwością około 1kHz while (1) { while(PINB & (1<<PB0)) ; // Czekamy na naciśnięcie klawisza v = TCNT0 % 6; // Zapamiętujemy stan licznika, będzie to wartość przypadkowa i = 6; // Dopóki przycisk naciśnięty, obracamy kostką do { PORTB = cube[i++]; if(i == 10) i = 6; _delay_ms(100); } while(!(PINB & (1<<PB0))); // wykonujemy jeszcze 10 dodatkowych obrotów kostką for(c = 0; c < 10; c++) { PORTB = cube[i++]; if(i == 10) i = 6; _delay_ms(100); } PORTB = 0b100001; // Gasimy wszystkie diody // Przez 3 sekundy wyświetlamy oczka - istnieje możliwość przerwania przyciskiem for(c= 0; (c < 30) && (PINB & (1<<PB0)); c++) { PORTB = cube[v]; // Wyświetlamy oczka kostki _delay_ms(100); PORTB = 0b100001; // Gasimy wszystkie diody } // Wykonujemy 10 mrugnięć - jeśli przycisk wciśnięty, operacja przerwana for(c= 0; (c < 10) && (PINB & (1<<PB0)); c++) { PORTB = cube[v]; _delay_ms(200); PORTB = 0b100001; // Gasimy wszystkie diody _delay_ms(100); } } } |
Program działa następująco:
Wchodzimy w pętlę główną. Na początku tej pętli czekamy na naciśnięcie przycisku, testując stan linii PB0. Jeśli linia ta przyjmie 0, to pętla testująca zostaje przerwana. W tym momencie odczytujemy stan licznika, dzielimy go przez 6 i w zmiennej v zapamiętujemy resztę z tego dzielenia. Reszta ma wartość od 0 do 5 i określa liczbę oczek kostki - 1. Wartość ta posłuży do znalezienia w tabeli cube odpowiedniego wpisu do PORTB. Najpierw jednak wchodzimy w drugą pętlę, która symuluje obroty kostki. Pętla ta jest wykonywana dotąd, aż zostanie zwolniony przycisk. Wtedy wchodzimy w następną pętlę, która wykonuje jeszcze dodatkowe 10 obrotów kostki. Po zakończeniu tej pętli gasimy zapobiegawczo wszystkie diody, po czym wchodzimy w kolejną pętlę, która tym razem wyświetla wylosowane oczka. Petla ta wykonuje się przez 3 sekundy lub krócej, jeśli w międzyczasie zostanie wciśnięty przycisk. Gdy ta pętla się zakończy, mikrokontroler wykonuje ostatnią pętlę, która mruga zapalonymi diodami LED, po czym gasi je (dla oszczędności, ekologia rulez!). Ostatnia pętla również jest przerywana przy naciśniętym przycisku – te przerwania zwiększają dynamikę działania całego urządzenia. Inaczej użytkownik musiałby czekać z naciśnięciem klawisza na koniec całego cyklu, a tak może rozpocząć nowy cykl praktycznie w dowolnym momencie. Gdy ostatnia pętla zakończy działanie, następuje powrót na początek pętli głównej i ponowne oczekiwanie na naciśniecie przycisku – zwróć jednak uwagę, że jeśli przycisk jest naciśnięty, to nowy cykl rozpoczyna się od razu.
Ponieważ zbliża się koniec roku szkolnego, kończymy zajęcia na kole informatycznym. Od przyszłego roku będziemy kontynuować kurs programowania mikrokontrolerów ATMEL. Zaczniemy do nich podłączać różne czujniki oraz układy wykonawcze i docelowo zbudujemy małego, ruchomego robota, który będzie się inteligentnie poruszał w środowisku.
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