Elektroda.pl
Elektroda.pl
X
Elektroda.pl
Proszę, dodaj wyjątek dla www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

Dokładny pomiar czasu na '51 z kwarcem 12MHz

05 Kwi 2005 00:54 3320 7
  • Specjalista techniki cyfrowej
    W jednym z tematów znalazłem coś takiego:
    Tdv napisał:
    Proponuję nie wprowadzać ludzi w błąd. Dokładny pomiar czasu przy pomocy uC '51 tylko i wyłącznie na kwarach 11,0592 itp i żadnych 12 ani 24 MHz!!!


    Nie wierzę, twierdzę wręcz, że to herezja :D
    Jest tam też link do FAQ
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=112417#112417
    a w tym FAQ czegoś mi brakuje.
    Kto powiedział, że timer musi pracować w trybie 1?
    Ja zawsze robię to tak, że mam timer w trybie 2 (autoreload) ustawiony, żeby przeładowywał wartość 6, co na kwarcu 12MHz daje przerwanie 4000 razy / sekundę, a dalej jest dzielone programowo. można np. dzielić przez 40 i będzie wtedy pomiar z dokładnością do 10ms, potem przez 100 i mamy sekundy itd.

    A kilka razy spotykałem się na forum z twierdzeniem, że pomiar czasu na kwarcu 12MHz nie ma prawa być dokładny, a na 11.0592MHz owszem.
    Wiem, że temat był już poruszany wielokrotnie, nawet użyłem Szukaj, ale nie znalazłem żadnego uzasadnienia dla słów zacytowanych powyżej. W związku z tym pytam, czy kolega Tdv ma rację, czy też nie?
    Nie, żebym się czepiał, czy coś :D . Skaładam zegarek, już drugi działający na tej zasadzie i po prostu chcę mieć pewność, że dobrze działa :D
  • Pomocny post
    Poziom 16  
    Witam
    Dobrze działa. Te 11,.... to pozostałość po kursach z serii AVT-łatwiej można było kontrolować port szeregowy.
  • Pomocny post
    VIP Zasłużony dla elektroda
    A ja śmiem twierdzić że jeszcze dokładniejszy pomiar czasu będzie na oscylatorze zegarkowym 32768Hz :D
    Najlepiej to się robi na Timer2 w trybie asynchronicznym (zegar procesora jest sobie np. 18.432MHz[bardzo sympatycznie podzielne dla UART-a], a na innych wyprowadzeniach sobie tyka oscylator zegarkowy), występującym w niektórych AVR.
    P.S. W dobie internetu szkoda drzew w lesie na papier do tych gazet, które nie uczą samodzielnego myślenia, tylko powielania cudzych pomysłów...
    Pozdrawiam, Light-I
  • Pomocny post
    Poziom 33  
    shg napisał:
    W jednym z tematów znalazłem coś takiego:
    Proponuję nie wprowadzać ludzi w błąd. Dokładny pomiar czasu przy pomocy uC '51 tylko i wyłącznie na kwarach 11,0592 itp i żadnych 12 ani 24 MHz!!

    Nie wierzę, twierdzę wręcz, że to herezja :D
    Jest tam też link do FAQ
    https://www.elektroda.pl/rtvforum/viewtopic.php?p=112417#112417
    a w tym FAQ czegoś mi brakuje.
    Kto powiedział, że timer musi pracować w trybie 1?
    Ja zawsze robię to tak, że mam timer w trybie 2 (autoreload) ustawiony, żeby przeładowywał wartość 6, co na kwarcu 12MHz daje przerwanie 4000 razy / sekundę, a dalej jest dzielone programowo. można np. dzielić przez 40 i będzie wtedy pomiar z dokładnością do 10ms, potem przez 100 i mamy sekundy itd.

    A kilka razy spotykałem się na forum z twierdzeniem, że pomiar czasu na kwarcu 12MHz nie ma prawa być dokładny, a na 11.0592MHz owszem.
    Wiem, że temat był już poruszany wielokrotnie, nawet użyłem Szukaj, ale nie znalazłem żadnego uzasadnienia dla słów zacytowanych powyżej. W związku z tym pytam, czy kolega Tdv ma rację, czy też nie?
    Nie, żebym się czepiał, czy coś :D . Skaładam zegarek, już drugi działający na tej zasadzie i po prostu chcę mieć pewność, że dobrze działa :D



    OK to już wyjaśniam - tryb z autoprzeładowaniem ma jedną zasadniczą wadę - licznik ma tylko 8 bitów, jeżeli chcesz mieć jakiś "okrągły" okres odliczany to jeszce go musisz skrócić np. do 250 (czyli tak jak podałeś te 4000 przerwań na s). Wszystko ładnie - jest tylko jeden problem od przerwania do przerwania masz tylko 250 cykli maszynowych, jak od tego odejmiesz czas potrzebny na obsługę przerwania to Ci zostaną już tylko jakieś marne resztki czasu. To znaczy, że w sumie procesor nie będzie w stanie za brdzo nic innego zrobić (zakładając 50 cykli na obsługę przerwania uC zużyje na nie 20% swojego czasu!!!).
    Jeżeli jedyną funkcją uC ma być pomiar czasu to rozwiązanie jest dobre, ale jeżeli jeszcze w czasie rzeczywistym miałbyś robić jakiekolwiek obliczenia to zapomnij.
    BTW to jeżeli dokładnie poczytałeś tamte teksty to powinieneś zauwazyć, że nie tylko 11,0592MHz...

    MichalKl napisał:
    Witam
    Dobrze działa. Te 11,.... to pozostałość po kursach z serii AVT-łatwiej można było kontrolować port szeregowy.


    AVT jeszce nie było kiedy zaczynałem programować uC. BTW to moja opinia o AVT jest jednoznaczna i niezbyt pozytywna.
  • Pomocny post
    Poziom 28  
    Ale przeciez tryb 1 jest swietny do liczenia czasu z kwarcem 12MHz. Wystarczy w wygenerowanym przerwaniu zsumowac zawartosc licznika (ktory bedzie mial akurat wartosci bliskie 0) z zadanym czasem po jakim ma sie wygenerowac nastepne przerwanie. Bardzo dokladne proste i nie zajmujace czasu procesora.
    Pozdro
    Dexter
  • Specjalista techniki cyfrowej
    A ja mam oto takie przerwanie:
    Code:
    ;=================================================
    
    ; Timer 0 interrupt
    ;=================================================

       .org   0x000B
    t0intv:
       MOV      timer_xxx,   TL0            ;2 execution time measurement (start)
       PUSH   ACC                     ;2
       PUSH   PSW                     ;2

       DJNZ   clock_clk,  noclock         ;2
          MOV      clock_clk,   #iclock_clk   ;2

    ; hundreds of seconds
          INC      clk_x
          MOV      A,   clk_x
          CJNE   A,   #100,   no_clock_carry
          MOV      clk_x,   #0

    ;-------------------------------------------------------------------
    ; in case of lack of free interrupt execution cycles, below can be thrown
    ; out of interrupt, but it will be necesary only if two succesive
    ; interrupts execute in more than 250 cycles each
    ;-------------------------------------------------------------------

    ; seconds
          SETB   clk_refresh               ; need to refresh clock
          INC      clk_s
          MOV      A,   clk_s
          CJNE   A,   #60,   no_clock_carry
          MOV      clk_s,   #0
    ; minutes
          INC      clk_m
          MOV      A,   clk_m
          CJNE   A,   #60,   no_clock_carry
          MOV      clk_m,   #0
    ; hours
          INC      clk_h
          MOV      A,   clk_h
          CJNE   A,   #24,   no_clock_carry
          MOV      clk_h,   #0
          SETB   date_inc               ; increment date

    no_clock_carry:

    noclock:

       MOV      A,   btrig
       JZ      nobdebounce
       DJNZ   clock0,   nobdebounce      ;2 period=40ms
          MOV      clock0,   #iclock0   ;2 reset debounce timer
          MOV      btrig,   #0         ;2 reset button trigger

    nobdebounce:

       MOV      A,   breplock         ; buttons to clear (autorepeat)
       CPL      A
       ANL      A,   brep            ; get only active autorepeat buttons
       JZ      norepeat            ; nothing to do, there are no autorepeat
                               ; buttons active, so don't start timer
       DJNZ   clock1,   notimerdiv      ;2 period=10ms - main divider
          MOV      clock1,   #iclock1   ;2 reset debounce timer

          DJNZ   clock2,   notimerdiv      ;2 period=300ms/100ms
             MOV      clock2,   #iclock2r   ;2 clock will be always reloaded
                                  ; with autorepeat delay, this can be
                                  ; altered by user.
             MOV      A,   breplock      ; execute command again
             ANL      brep,   A         ; clear only autorepeat buttons.
    notimerdiv:
    norepeat:

       POP      PSW               ;2
       POP      ACC               ;2
       MOV      timer_yyy,   TL0      ;2 execution time measurement
       RETI


    MOV na początku i na końcu pomijamy, jak jest napisane - pomiar czasu wykonywania (wychodzi 20 cykli)
    Sobie to tak sprytnie zrobiłem, że obsługa zegara wykonywana jest w coczterdziestym przerwaniu.
    a więc 39 z 40 przerwań wygląda tak:
    2 cykle zmarnowane na skok do przerwania
    4 cykle - zrzucanie rejestrów na stos
    2 cykle na DJNZ
    5 cykli MOV / JZ / DJNZ
    5 cykli MOV / CPL / ANL / JZ (DJNZ tylko jeżeli jest aktywna klawiatura - przez większość czasu nie jest)
    4 cykle zdejmowanie ze stotu
    2 cykle na powrót.
    suma: 22 cykle
    22/250=8.8% Czyli nie jest tak źle, zresztą i tam mam wyświetlanie na LCD, więc jak trochę "poszarpie", to się nic nie stanie :D
    Będzie do tego jeszcze EEPROM 24C08 i synteza SAA1057.

    A obliczenia w czasie rzeczywistym - wszystko da się zrobić inaczej :D
    W poprzednim zegarze było jeszcze sterowanie 6 wyświetlaczami LED + kontrolki, podobna procedura do zliczania czasu, stoper i timer, ale chodziło (i chodzi dalej :D ) to na kwarcu 6MHz (musiałem się z całym przerwaniem w 125 cyklach zmieścić a jeszcze trzeba było "obrabiać" klawiaturę, 8(!) budzików, itd. :D ) (a zresztą, na mojej stronie jest cały projekt) Wszystko da się zrobić, trzeba tylko posiedzieć.

    A co do AVT - chałę odwalają niemiłosierną. Tam to już absolutne zonki się działy, jeżeli chodzi o odmierzanie czasu - zatrzymywanie timera, milczące zakładanie, że od wystąpienia przepełnienia w timerze, do rozpoczęcia obsługi przerwanie jest chyba 56 cykli (bascom bezmózgi - wszystko na stos, niezależnie, czy jest używane, czy nie, w każdym przerwaniu marnowanie 100 cykli :D ) a tak naprawdę to tych cykli było od 56 do 60, w zależności od tego, w którym miejscu wystąpiło przerwanie


    A jak już jest o dokładności, to może ma ktoś pomysł, jak za pomocą trymera dostroić kwarc dokładnie do 12 MHz?

    Wymyśliłem, taki patent, żeby np. timer 0 zliczał taktowany z oscylatora na procku, a timer 1 taktowany byłby z oscylatora 32768Hz
    No i jakoś zliczone wartości porównać np. timer w trybie 1 i każde przepełnienie oznacza 2 sekundy. potem odczyt timera 0, timera 1 (w tej kolejności), korekcja opóźnienia uruchomienia obsługi przerwania.

    Dało by się tak? Ktoś może eksperymentował?
  • Pomocny post
    Poziom 18  
    Jeśli nie musisz, to nie zliczaj czasu w przerwaniu. Jedyną rzecz jaką wstaw do przerwania to ustawianie jakiejś flagi "nastepna_sekunda". Cała reszta powinna się znaleźć w głównej pętli programu.
  • Specjalista techniki cyfrowej
    Wszystko jasne. Mozna zamknąć.
    Dzięki za odpowiedzi!