Programowanie mikrokontrolerów Marcin Engel Marcin Peczarski 3 stycznia 2008
Liczniki, cd. Przypomnienie wiadomości o liczniku 0 Przykładowy program korzystający z licznika Ćwiczenia praktyczne
Licznik 0, tryb normalny normalny tryb pracy: licznik zlicza od 0 do 255 i potem znów od zera w chwili przepełnienia jest ustawiany znacznik TOV0 gdy licznik osiąga wartość rejestru OCR0, jest ustawiany znacznik OCF0 zmiany wartości OCR0 są natychmiastowe
Licznik 0, tryb CTC tryb CTC (Clear Timer on Compare): licznik zlicza od 0 do OCR0 i potem znów od zera w chwili przepełnienia jest ustawiany znacznik TOV0 gdy licznik osiąga wartość rejestru OCR0, jest ustawiany znacznik OCF0 zmiany wartości OCR0 są natychmiastowe
Licznik 0, przerwania mogą (nie muszą) być wyzwalane przerwanie przepełnienia wyzwalane ustawieniem flagi TOV0 (adres OVF0addr) przerwanie zgodności wyzwalane ustawieniem flagi OCR0 (adres OC0addr) powrót z przerwania automatycznie zeruje flagi można je wyzerować ręcznie ustawiając je na 1!
Licznik 0, preskaler Licznik może być: zatrzymany taktowany częstotliowością zegara taktowany częstotliwością 8, 64, 256 lub 1024 razy mniejszą niż zegar procesora taktowany sygnałem na nodze T0
Licznik 0, noga OC0 (PB3) Licznik można skonfigurować tak, że każde wykrycie zgodności powoduje zmianę poziomu na wyjściu OC0 Obsługa OC0 jest sprzętowa, tzn. wystarczy skonfigurować odpowiednio licznik, potem program nie musi się już niczym zajmować
Uwagi Rozdzielczość licznika można zwiększyć programowo poprzez umiejętną obsługę przerwania przepełnienia W trybie CTC przepełnienie może nigdy nie wystąpić W trybie CTC trzeba uważać zmieniając wartość OCR0 zmiana może zgubić się w jednym cyklu licznika
Przykład Zrobimy prosty jednogłosowy, jednooktawowy instrument muzyczny Założenia: przyciski mają działać jak jednooktawowa klawiatura fortepianowa (bez czarnych klawiszy!) przycisk SW7 ma powodować wygenerowanie tonu C2, SW6 tonu D2 itd. dźwięk ma trwać tak długo, jak długo wciśnięty jest przycisk nie precyzujemy, co się stanie przy wciśnięciu dwóch przycisków jednocześnie
Głośnik płytka zawiera tzw. przetwornik piezo z generatorem, czyli głośniczek z generatorem tonu o określonej częstotliwości nie nadaje się on do naszych celów ze względu na wbudowany generator podłączymy zewnętrzny przetwornik bez generatora
Zakres częstotliwości kamertonowe A1 to dźwięk o częstotliwości 440 Hz dźwięki odległe o oktawę mają stosunek częstotliwość równy 2 oktawa składa się z 12 półtonów stosunek częstotliwości kolejnych półtonów jest taki sam... 12... i wynosi 2 Stąd C2 to 440 4 2 523.3 Hz. C3 to 523.3 2 = 1046, 6 Hz
Jaki tryb pracy? Oczywiście CTC! Wtedy rejestr OCR0 posłuży do uzyskania odpowiedniej częstotliwości Głośnik podłączymy do PB3 (OC0) i ustawimy licznik tak, żeby poziom na tej nodze był zmieniany sprzętowo przy uzyskaniu zgodności (gdy licznik osiągnie wartość maksymalną, czyli OCR0)
Jak ustalić wartość OCR0 dla dźwięku C2? C2 to 523.3 Hz Przypomnijmy, że zgodność w trybie CTC występuje z częstotliwością clk (OCR0 + 1) N Częstotliwość dźwięku będzie równa połowie tej częstotliwości, bo pełny okres wymaga dwóch zmian poziomów Stąd: OCR0 = clk 2 f N 1
Jak dobrać wartość preskalera N? Z jednej strony, powinna być jak najmniejsza, żeby uzyskać dobrą dokładność Z drugiej strony, dla najniższej częstotliwości f dźwięku, powinniśmy uzyskać wartość 8-bitową Policzmy dla N = 1, f = 523.3 i clk = 1MHz: OCR0 = 1000000 2 523.3 1 1 954 Za dużo, ale dla następnej możliwej wartości N = 8 będzie dobrze: OCR0 = 1000000 2 523.3 8 1 118
Tabela wartości OCR0 dźwięk OCR0 C2 118 D2 105 E2 94 F2 88 G2 79 A2 70 H2 62 C3 59
Algorytm 1. Konfigurujemy licznik 0 do pracy w trybie CTC, preskalerem 1/8, ale go nie włączamy 2. Konfigurujemy nogę PB3 jako wyjście 3. W pętli nieskończonej: skanujemy przyciski gdy wykryjemy wciśnięty klawisz, odszukujemy odpowiednią wartość w tabeli, ładujemy ją do OCR0 i uruchamiamy licznik gdy żaden klawisz nie jest wciśnięty stopujemy licznik
Uwagi Zatrzymanie licznika nie zeruje go Możemy przełączać PB3 w stan wysokiej rezystancji zamiast stopować licznik Nie przejmujemy się drganiem styków, nie mają one dużego znaczenia w tej aplikacji Nie przejmujemy się też ewentualnymi zaburzeniami (w obrębie jednego okresu) częstotliwości
Gdzie umieścić tabelę W pamięci programu! Pamiętamy o przeliczaniu adresu (mnożnik 2) Specjalny rozkaz lpm r, Z powoduje załadowanie do rejestru r wartości spod adresu wskazywanego przez rejestr Z w pamięci programu
Typowy kod ldi zh, high (tabela*2) ldi zl, low (tabela*2) szukaj:... lpm temp, Z... adiw zh:zl, 1 rjmp szukaj lub szukaj:... lpm temp, Z+... rjmp szukaj
Przesunięcia logiczne i arytmetyczne lsl r17: C b 7... b 0 0 lsr r17: 0 b 7... b 0 C asr r17: jak wyżej ale bit b 7 jest powielany, nie zerowany rol r17: C b 7... b 0 C ror r17: C b 7... b 0 C
I przydatne w tym kontekście rozkazy brcs adres: skocz pod adres jeśli C ustawiony brcc adres: skocz pod adres jeśli C wyzerowany sec: ustaw C clc: wyzeruj C
Porty wejścia/wyjścia, przypomnienie Rejestr DDRC ustala kierunek pracy: 0 wejście, 1 wyjście, np.: sbi ddrc, 5 Odczyt stanu nogi odbywa się z PINC Ustawienie stanu nogi odbywa się przez PORTC
Schemat podłączeń, VMLab K0 pc0 gnd K1 pc1 gnd K2 pc2 gnd K3 pc3 gnd K4 pc4 gnd K5 pc5 gnd K6 pc6 gnd K7 pc7 gnd R0 pc0 vdd 1k R1 pc1 vdd 1k R2 pc2 vdd 1k R3 pc3 vdd 1k R4 pc4 vdd 1k R5 pc5 vdd 1k R6 pc6 vdd 1k R7 pc7 vdd 1k.plot V(pb3)
Schemat połączeń, płytka głośnik (wypożyczany od prowadzących) do GND i PB3 SW0 do PC0 SW1 do PC1... SW7 do PC7
Program, definicje.def temp = r17 ; Licznik zatrzymany, zmiana poziomu na OC0, tryb CTC:.equ C_STOP = (1 << wgm01) ( 1 << com00) ; Licznik zatrzymany, zmiana poziomu na OC0, tryb CTC:.equ C_START = C_STOP ( 1 << cs01)
Program, standardowy początek.cseg.org 0 reset: jmp start.cseg.org 42 ; pierwszy adres za wektorem przerwa«start:
Program, konfiguracja ; konfiguracja licznika 0: ldi temp, C_STOP out TCCR0, temp ; konfiguracja portu PB3 jako wyjscia sbi ddrb, PB3
Program, główna pętla forever: ; skanowanie klawiatury ; Wczytujemy stan klawiszy i negujemy wszystkie bity in temp, pinc com temp ; Operacja com ustawi flage Z, jesli byly same jedynki ; Skaczemy do wylacz, jesli zaden klawisz nie wcisniety breq wylacz ; do Z zmniejszony o 1 adres poczatku tabeli ldi zl, low (2*tabela-1) ldi zh, high (2*tabela-1)
Program, szukanie ustawionego bitu szukaj: ; przewijamy rejestr temp ladujac do C kolejne bity ; w kazdym obrocie zwiekszamy Z o 1 tak, aby zawieral ; adres pozycji tabeli odpowiadajacy kolejnemu ; klawiszowi adiw zh:zl, 1 lsl temp ; jesli nie wcisniety, szukaj dalej brcc szukaj
Program, graj dźwięk ; znalezlismy wcisniety klawisz ; odczytujemy z tabeli odpowiadajaca mu wartosc OCR0 lpm temp, Z out ocr0, temp ; wlaczamy licznik ldi temp, C_START out tccr0, temp rjmp forever
Program, wyłącz dźwięk wylacz: ; wylaczamy dzwieki ldi temp, C_STOP out tccr0, temp rjmp forever tabela:.db 118, 105, 94, 88, 79, 70, 62, 59
Ćwiczenia jeszcze świąteczne i nie tylko Zagraj na wykonanym przez siebie instrumencie: :-)
(zaległe) Wygeneruj na PB3 sygnał o częstotliwości 1 Hz (zaległe) Napisz elektroniczną ruletkę (zaległe) Wykonaj lampki choinkowe : zapalaj po kolei po jednej diodzie z częstotliwością zmienianą przyciskami SW0 i SW7. Do odmierzania czasu użyj licznika!