logo elektroda
logo elektroda
X
logo elektroda
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

[Bascom AVR] niewygodne odmierzanie czasu za pomocą timer ów

MES Mariusz 09 Paź 2009 23:02 8423 4
  • #1 7109651
    MES Mariusz
    Poziom 36  
    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.

    '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
    
  • Pomocny post
    #2 7109694
    grysek
    Poziom 19  
    Timer0 jest 8-bitowy czyli pomiesci liczbę z zakresu 0-255, Timer1 jest 16-bitowy czyli pomiesci liczbę z zakresu 0 - 65535. Zapewne autorowi chodziło o to aby zrobić to na timerze 8-bitowym, ale Twoje obliczenia tez są dobre tylko dla Licznika/Timera1
  • #3 7109863
    Konto nie istnieje
    Poziom 1  
  • #4 7109886
    mirekk36
    Poziom 42  
    A ja proponuję może najpierw się zastanowić nad tym do czego opóźnienia i wtedy dobrać sposób czy na timerze czy bez timera.

    Tak mi się wydaje, że próby zaprzęgania Timerów do super "idealnego" odmierzania tak gigantycznego czasu jak 1 sekunda to jak strzelanie z armaty do komara (choć może się mylę - ale ciekaw jestem do czego tak na prawdę może być potrzebne aż tak dokładne odliczanie 1 sekundy poza czysto akademickimi przykładami)

    Timery zaczynają się bardzo przydawać gdy trzeba odmierzać jakieś o wiele mniejsze odcinki czasu niż sekunda.

    I wtedy warto po pierwsze zapoznać się z użytkowaniem Timera w trybie CTC - jeśli timer taki tryb posiada - to po pierwsze

    a po drugie wcale nie trzeba zaprzęgać do tego przerwań.

    Np można w pętli głównej odmierzać sobie jakieś super dokładne odcinki czasu rzędu np mikrosekund czy milisekund - nie włączając przerwań tylko odpalając timer i następnie czekać w pętli na stosowną FLAGĘ przerwania danego Timera w odpowiednim rejestrze.

    Jeśli chodzi natomiast o to aby jakieś przerwanie wykonywało się w miarę bardzo precyzyjnie - (co i tak przeważnie nie jest najczęściej do spełnienia jeśli mają działać w międzyczasie inne przerwania) to właśnie warto użyć szczególnie w takim przypadku tybu CTC - gdzie programowo ładujesz sobie rejestr OCRx jakąś wartością przepełnienia i korzystasz z przerwania Capture. Dzięki czemu w samym przerwaniu nie musisz wciąż ładować zmiennej Timer, przeliczać sobie w międzyczasie wartości itp

    reasumując - odmierzanie czasu za pomocą Timerów jest bardzo ale to bardzo wygodne - tylko zależy od tego do czego? i jak to się używa
  • #5 7110031
    MES Mariusz
    Poziom 36  
    atom1477 napisał:
    Dokładnie tak.
    Ale skąd wziąłeś liczbę 63566?

    Taki inny rodzaj literówki ;-) Oczywiście chodziło o 65535
REKLAMA