Witam.
To tej pory nie stosowałem zbyt często timerów do generowania przerwań celem generowania odcinków czasu. Być może dlatego żyłem w słodkiej nieświadomości pewnych komplikacji będących nie bez wpływu na dokładność odmierzanych odcinków czasu.
Do tej pory wydawało mi się, że dla danego rezonatora kwarcowego wystarczy:
1. Obliczyć czas trwania pojedynczego cyklu maszynowego
2. Sprawdzić ile takich odcinków czasu potrzebuję do uzyskania potrzebnego mi czasu
3. Jeśli liczba potrzebnych cykli przekracza 63566 zastosować prescaler i sprawdzić ile takich odcinków czasu z zastosowaniem prescalera potrzebuję do uzyskania potrzebnego mi czasu
4. Skonfigurować timer, do rejestru timera wpisać wartość będącą różnicą 63566 oraz potrzebnej ilości cykli po przeskalowaniu.
5. Uruchomić timer i przerwania.
Przykładowo dla uzyskania 1 sekundowych odcinków przy kwarcu 8 MHz:
Czas pojedynczego taktu = 125 ns czyli potrzebuję 8000000 takich cykli dla uzyskania 1s.
Ponieważ timer zlicza od 0 do 63566 nie jestem w stanie zliczyć 8000000 taktów więc stosuję prescaler o wartości 256.
Po tej operacji "pojedynczy cykl" wynosi 32 µs, więc dla uzyskania 1 s potrzebuję 31250 takich cykli. Ta wartość oczywiście już się mieści w przedziale 0...63566.
Wystarczyłoby więc do timera załadować wartość 63566 - 31250 = 32316.
Timer zliczałby od 1 do 31250 i dokładnie co sekundę generowane byłoby jedno przerwanie.
Żeby się jednak upewnić, zerknąłem do książki Programowanie mikrokontrolerów w języku Bascom Marcina Wiązani i co widzę? Kombinacje alpejskie (listing poniżej).
Czyli konfigurowanie timera na odliczanie odcinków 8 ms (wróżba że, 250 odcinków po 32 µs da nam magiczne 8 ms) a potem dopiero zliczenie, o zgrozo, 125 wygenerowanych przerwań, co w sumie da nam przybliżony czas 1 s. Przybliżony, bo przecież dochodzi czas obsługi przerwań, jak choćby wspomniane przez autora wstawianie za każdym razem do rejestru wartości 250.
A wszystko to przez to, że, jeśli dobrze zrozumiałem, do rejestru można wpisać co najwyżej wartość mieszczącą się w zmiennej typu byte. Czyli nie da się wpisać mojego 31250, a co najwyżej 255 (autor wpisuje tam 250 tworząc 8 ms odcinki).
Dziwne, timer zlicza od 0 do 63566 (a więc zakres sporo wykraczający poza bajta) a do rejestru można wpisać tylko bajta?
Straszne kombinowanie z tymi wyliczeniami.
To tej pory nie stosowałem zbyt często timerów do generowania przerwań celem generowania odcinków czasu. Być może dlatego żyłem w słodkiej nieświadomości pewnych komplikacji będących nie bez wpływu na dokładność odmierzanych odcinków czasu.
Do tej pory wydawało mi się, że dla danego rezonatora kwarcowego wystarczy:
1. Obliczyć czas trwania pojedynczego cyklu maszynowego
2. Sprawdzić ile takich odcinków czasu potrzebuję do uzyskania potrzebnego mi czasu
3. Jeśli liczba potrzebnych cykli przekracza 63566 zastosować prescaler i sprawdzić ile takich odcinków czasu z zastosowaniem prescalera potrzebuję do uzyskania potrzebnego mi czasu
4. Skonfigurować timer, do rejestru timera wpisać wartość będącą różnicą 63566 oraz potrzebnej ilości cykli po przeskalowaniu.
5. Uruchomić timer i przerwania.
Przykładowo dla uzyskania 1 sekundowych odcinków przy kwarcu 8 MHz:
Czas pojedynczego taktu = 125 ns czyli potrzebuję 8000000 takich cykli dla uzyskania 1s.
Ponieważ timer zlicza od 0 do 63566 nie jestem w stanie zliczyć 8000000 taktów więc stosuję prescaler o wartości 256.
Po tej operacji "pojedynczy cykl" wynosi 32 µs, więc dla uzyskania 1 s potrzebuję 31250 takich cykli. Ta wartość oczywiście już się mieści w przedziale 0...63566.
Wystarczyłoby więc do timera załadować wartość 63566 - 31250 = 32316.
Timer zliczałby od 1 do 31250 i dokładnie co sekundę generowane byłoby jedno przerwanie.
Żeby się jednak upewnić, zerknąłem do książki Programowanie mikrokontrolerów w języku Bascom Marcina Wiązani i co widzę? Kombinacje alpejskie (listing poniżej).
Czyli konfigurowanie timera na odliczanie odcinków 8 ms (wróżba że, 250 odcinków po 32 µs da nam magiczne 8 ms) a potem dopiero zliczenie, o zgrozo, 125 wygenerowanych przerwań, co w sumie da nam przybliżony czas 1 s. Przybliżony, bo przecież dochodzi czas obsługi przerwań, jak choćby wspomniane przez autora wstawianie za każdym razem do rejestru wartości 250.
A wszystko to przez to, że, jeśli dobrze zrozumiałem, do rejestru można wpisać co najwyżej wartość mieszczącą się w zmiennej typu byte. Czyli nie da się wpisać mojego 31250, a co najwyżej 255 (autor wpisuje tam 250 tworząc 8 ms odcinki).
Dziwne, timer zlicza od 0 do 63566 (a więc zakres sporo wykraczający poza bajta) a do rejestru można wpisać tylko bajta?
Straszne kombinowanie z tymi wyliczeniami.
'Przyk³ad wykorzystania Timer0 do generowania w przerwaniu
'1 sekundowych odcinków czasu
'Program co sekundê w przerwaniu zmienia na przeciwny stan linii
'PD0 steruj¹cej diod¹ LED
'Przerwanie od przepe³nienia Timer0 jest generowane co 8 ms
'- 8MHz/256/250 = 125, a 1/125 s = 8 ms
'Zliczenie 125 odcinków 8 ms da 1 sekundê
$regfile = "m8def.dat" 'informuje kompilator o pliku
'dyrektyw mikrokontrolera
$crystal = 8000000 'informuje kompilator o
'czêstotliwoœci oscylatora
'taktuj¹cego mikrokontroler
Config Pind.0 = Output 'linia PD0 jako wyjœciowa
Config Timer0 = Timer , Prescale = 256
'konfiguracja Timer0 jako timera
'z podzia³em preskalera przez
'256
On Timer0 Odmierz_1s 'przerwanie od przepe³nienia
'Timer0 o etykiecie Odmierz_1s
Dim Licz_8ms As Byte 'zmienna pomocnicza zliczaj¹ca
'odcinki czasu równe 8 ms
Enable Interrupts 'odblokowanie globalnego systemu
'przerwañ
Enable Timer0 'odblokowanie przerwania od
'przepe³nienia Timer0
Load Timer0 = 250 'wartoœæ pocz¹tkowa Timer0
Do 'pêtla nieskoñczona
Loop
End 'koniec programu
Odmierz_1s: 'pocz¹tek podprogramu obs³ugi
'przerwania od przepe³nienia
'Timer0
Load Timer0 = 250 'wartoœæ pocz¹tkowa Timer0
Incr Licz_8ms 'zwiêksz o jeden wartoœæ
'zmiennej pomocniczej Licz_8ms
If Licz_8ms = 125 Then 'je¿eli wartoœæ tej zmiennej
'równa 125 (125*8 ms = 1) to
'odliczono 1 sekundê
Licz_8ms = 0 'zerowanie zmiennej licznikowej
Toggle Portd.0 'zmieñ na przeciwny stan linii
'PD0 portu D mikrokontrolera
End If 'koniec warunku If...Then
Return 'powrót z przerwania
