Witam kolegów,
głowię się już ładnych parę dni nad taką kwestią w procku:
zrobiłem na Atmedze8 zegarek. Zewnętrzny kwarc 4MHz. Timer1 zajmuje się odliczaniem równych sekund, Timer0 osługą wyświetlania itp.
Na czym polega problem? Zegarek spóźnia się, wg moich obliczeń na symulatorze w AVR Studio, o 0,345s na dobę. Nie jest to szok ani porażka, raptem 2 minuty rocznie, ale jednak chciałbym wiedzieć skąd bierze się to opóźnienie. Opóźnienie widać gołym okiem już po pierwszej dobie (w porównaniu z kwarcowym zegarem ściennym).
Skąd te wyliczenia? Już tłumaczę. Timer1 skonfigurowany jest tak:
co daje przerwanie co równą sekundę.
Przy każdym przerwaniu Timer1 ładuję do niego ponownie 3036, oczywiście.
Po tym jak zacząłem dociekać przyczyny spóźnienia, wydedukowałem przy pomocy symulatora, że problem może tkwić tutaj:
Otóż po wywołaniu przerwania TIMER1_OVF zanim wpiszę do niego wartość 3036, upływa 4us. Czas zwiększania licznika TIMER1 wynosi 16us, co oznacza, że co cztery "takty" tego timera gubię 1 z jego wartości. Na dobę daje to stracone 900. Jest to właśnie brakujące 0,345s.
Jak to załatać? Próbowałem korygować w TIMER0 wartość TIMER1, co godzinę dodając brakujące 900 (pierwsza sekunda każdej godziny nieco krótsza), ale ku mojemu zdziwieniu, po jednej dobie zegarek spóźnia się już dobre 3 sekundy.
Efekt całkiem odwrotny.
Proszę w takim razie o opinię gdzie może leżeć problem i/lub co jest błędnego w moim rozumowaniu/wyliczeniach.
------------------------------
Dodam jeszcze, żeby uprzedzić pytania, że czas wykonania procedury w przerwaniu T1 jest znikomy, są tam tylko 3 instrukcje, czas wykonania T0, który cyka co 2ms, jest poniżej 0,3ms, więc też ze spokojnym zapasem.
Kwarc niski z kondensatorami 33p, cały układ zasilany z zasilacza ATX linii +12V przez stabilizator 7805, więc "podwójnie" stablilizowany.
głowię się już ładnych parę dni nad taką kwestią w procku:
zrobiłem na Atmedze8 zegarek. Zewnętrzny kwarc 4MHz. Timer1 zajmuje się odliczaniem równych sekund, Timer0 osługą wyświetlania itp.
Na czym polega problem? Zegarek spóźnia się, wg moich obliczeń na symulatorze w AVR Studio, o 0,345s na dobę. Nie jest to szok ani porażka, raptem 2 minuty rocznie, ale jednak chciałbym wiedzieć skąd bierze się to opóźnienie. Opóźnienie widać gołym okiem już po pierwszej dobie (w porównaniu z kwarcowym zegarem ściennym).
Skąd te wyliczenia? Już tłumaczę. Timer1 skonfigurowany jest tak:
Code:
TCNT1 = 3036; // wartość początkowa
TCCR1A = 0x00; // timer1 w trybie czasomierza
TCCR1B = (1 << CS11) | (1 << CS10); // preskaler 64
co daje przerwanie co równą sekundę.
Przy każdym przerwaniu Timer1 ładuję do niego ponownie 3036, oczywiście.
Po tym jak zacząłem dociekać przyczyny spóźnienia, wydedukowałem przy pomocy symulatora, że problem może tkwić tutaj:
Code:
ISR (TIMER1_OVF_vect) {
TCNT1 = 3036;
Otóż po wywołaniu przerwania TIMER1_OVF zanim wpiszę do niego wartość 3036, upływa 4us. Czas zwiększania licznika TIMER1 wynosi 16us, co oznacza, że co cztery "takty" tego timera gubię 1 z jego wartości. Na dobę daje to stracone 900. Jest to właśnie brakujące 0,345s.
Jak to załatać? Próbowałem korygować w TIMER0 wartość TIMER1, co godzinę dodając brakujące 900 (pierwsza sekunda każdej godziny nieco krótsza), ale ku mojemu zdziwieniu, po jednej dobie zegarek spóźnia się już dobre 3 sekundy.
Efekt całkiem odwrotny.
Proszę w takim razie o opinię gdzie może leżeć problem i/lub co jest błędnego w moim rozumowaniu/wyliczeniach.
------------------------------
Dodam jeszcze, żeby uprzedzić pytania, że czas wykonania procedury w przerwaniu T1 jest znikomy, są tam tylko 3 instrukcje, czas wykonania T0, który cyka co 2ms, jest poniżej 0,3ms, więc też ze spokojnym zapasem.
Kwarc niski z kondensatorami 33p, cały układ zasilany z zasilacza ATX linii +12V przez stabilizator 7805, więc "podwójnie" stablilizowany.