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

AVR - Timer 1 w AVR - przerwanie nie działa jak powinno

tomeeh 15 Sty 2014 12:35 4752 10
  • #1 13179066
    tomeeh
    Poziom 24  
    Witam,

    mam chyba dość banalny problem z timerem T1 w ATtiny45. Otóż celem jest generowanie przerwania co około 40 ms - czyli zadanie wydaje się praktycznie śmiesznie proste. Proste było w 8051, ale AVR mi się stawia.
    Do tego celu zaprzągnąłem timer T1 w konfiguracji „match compare”. Przy kwarcu 8 MHz, preskalerze 2048 oraz wartości OCR1A = 156 powinienem uzyskać przerwanie co 39,9 ms [ (1/8 MHz) * 2048 * 156 = 39,9 ms]. Kod zamieszczam poniżej:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    W obsłudze przerwania wstawiłem Breakpointa.

    Reakcja symulatora jest następująca:
    1. W Atmel Studio 6.1, pierwszy skok do obsługi przerwania występuje wprawdzie po około 40 milisekundach (super!), ale kolejne skoki do obsługi przerwania występują już co 65,5 milisekund (lipa!). Doszedłem do tego, że te 65,5 milisekund, to dokładnie tyle, ile potrzebuje timer by się przepełnić (skok z wartości 255 do 0). Nie rozumiem tego, bo przecież w moim OCR1A jest ciągle 156 i przerwanie jest tak skonfigurowane, że ma reagować na „match compare”, a nie na przepełnienie timera. No a nawet, jeśli miałoby to reagować na przepełnienie, to przecież obsługa tego jest pod innym wektorem przerwania, niż mój.

    2. W AVR Studio 4.19 w ogóle nie następuje skok do obsługi przerwania. Symulator i debugger działają (rejestry się zmieniają, program counter i stack pointer też nie stoją w miejscu), ale nie rozumiem, dlaczego przerwanie w ogóle nie jest obsługiwane.

    Widzicie tu błąd (błędy)? Dlaczego to nie działa zgodnie z założeniem? Czy Atmel robi jakąś lipę ze środowiskiem 4.19?
  • Pomocny post
    #2 13179240
    BlueDraco
    Specjalista - Mikrokontrolery
    Po pierwsze, zmień błędny tytuł wątku na "przerwanie nie działa tak, jak bym chciał".

    Po drugie, przeczytaj pierwszego zdanie opisu bitu CTC1 w datasheet i porównaj to, co pisze producent z tym, co wymyśliłeś.
  • Pomocny post
    #3 13179246
    dondu
    Moderator na urlopie...
    Witaj.

    Cytat:
     Bit 7 – CTC1 : Clear Timer/Counter on Compare Match
    When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare
    match with OCR1C register value
    . If the control bit is cleared, Timer/Counter1 continues counting and is unaffected
    by a compare match.

    EDIT:
    Znowu BlueDraco mnie wyprzedził :)
  • #4 13179908
    tomeeh
    Poziom 24  
    No dzięki Panowie,

    wiecie co jest najlepsze? Popatrzcie na cytat, ale tym razem z rozdziału 13 datasheeta (strona 100):

    Cytat:

    When the CTC1 control bit is set (one), Timer/Counter1 is reset to $00 in the CPU clock cycle after a compare match with OCR1A register.


    Widzicie to "OCR1A"? Z tym tylko, że rozdział 13 traktuje o timerze w trybie zgodności z ATtiny15. Czyli dałem się złapać przy przewijaniu dokumentu, bo opis trybu, którego potrzebuję to rozdział 12. Na nieszczęście, są to te same rejestry, więc nie zauważyłem, że jestem w innym dziale. No niezła pułapka.

    OK, super, w każdym razie software'owe wyzerowanie licznika w obsłudze przerwania natychmiast załatwiło sprawę (TCNT1 = 0;).


    Chciałbym jeszcze powrócić do pytania 2: dlaczego Symulator z AVR Studio 4.19 wraz z toolchainem 3.3.1 (wszystko pobrane ze stronki Atmela), przy identycznym kodzie nie wskakuje w obsługę przerwania? Sorry, że tak męczę, ale dopiero zaczynam zabawę z AVRami i jest to trochę denerwujące, bo pod 4.19 nie wiem, czy kod jest błędny, czy też jakiś problem z symulatorem.
  • #5 13180157
    BlueDraco
    Specjalista - Mikrokontrolery
    Czyli zamaskowałeś jeden błąd innym błędem i na pierwszy rzut oka rozwiązanie sprawia wrażenie działającego, a drugi raz już lepiej nie rzucać.
    Teraz czekamy na wątek pt. "zegarek na ATtiny się późni".
  • #6 13181059
    tomeeh
    Poziom 24  
    Witam,

    przesymulowałem sobie pierwsze 8 minut działania zegarka. Dokładnie patrzyłem (wartość Stop Watch w symulatorze), kiedy wchodzę do obsługi przerwania. W ciągu tych 8 minut (odpowiada to 12.000 wywołań tego przerwania) błąd był niewidoczny, tzn. symulator nie był w stanie stwierdzić wahań, tj. resztkowe opóźnienie wynosi poniżej 10 ns (najmniejsze ziarno w symulatorze). Chociaż mówić o 10 ns to bez sensu, bo jeden cykl zegarowy trwa przecież 125 ns. Czyli timer wystartował o czasie "4,75 us" i po 8 minutach odczytałem wartość "48 000 . 000 004 75 ms". Nie mam jeszcze wytłumaczenia, ale jeśli symulator nie kłamie, to jest idealnie. Oczywiście dodam, że zmniejszyłem wartość OCR1A o jeden w stosunku do kodu z mego pierwszego postu. I co czwarte przerwanie wydłużam cykl timera o jedność.

    Chociaż przyznam się bez bicia, że mam pewne obawy, bo od czasu wywołania przerwania do wyzerowania timera upłynie kilka cykli. Zakładając 5 cykli, uzyskuję błąd 0,625 us, co przy jednej dobie odpowiada 1 sekundzie opóźnienia. Tylko dlaczego symulator tego nie uwzględnia... Chwilowo pozostaje mi zaufać mu. Biorąc pod uwagę, że w zegarze będzie DCF-77, nie jest tragicznie. Zgodnie z obliczeniami, 30 ppm błędu kwarca (wartość z katalogu) może wprowadzić błąd 2,5 sekundy na dobę.
    Na marginesie: DCF będzie nie po to, by kompensować błędy w programie, po prostu od zawsze kocham DCF i jak dla mnie, to obowiązkowy punkt.

    Sam się zastanawiam, czy w ATtiny mogę zrobić to prościej. Otóż:
    1. Przy rozpatrzeniu Timera0, maksymalny preskaler to 1024, więc przy 8 MHz (tych 8 MHz nie chciałbym zmieniać) mogę maksymalnie uzyskać 32,768 ms, a jak wiadomo, potrzebuję 40 ms.
    2. Biorąc Timer1, mam preskaler 2048, ale tryb CTC mogę odnieść do komparatora C, ale komparator ten niestety nie ma swego wektora przerwania. Natomiast dla komparatorów A oraz B mających wektory przerwań nie znalazłem trybu CTC.
    3. Oczywiście ktoś może powiedzieć, że się uparłem na tego tiny, bo są przecież starsi bracia, gdzie można podać kwarc zegarkowy 32,768 kHz i skorzystać z RTC. No ale cóż, ja się tym razem uparłem na 8-nóżkowego tiny i kropka.

    @BlueDraco -> jeżeli nie jest to skrzętnie przez ciebie skrywaną tajemnicą, możesz śmiało napisać, jakie proponujesz rozwiązanie pozbawione błędów. Na pewno się nie obrażę!
    W końcu na błędach można się nauczyć.
  • #7 13181254
    BlueDraco
    Specjalista - Mikrokontrolery
    Zaprogramuj uczciwie timer w tryb CTC. O ile pamiętam (mogę się mylić, bo AVRy rzuciłem parę lat temu), to na końcu cyklu masz tu przerwanie od "zawinięcia" timera.
    Ogólnie nie jest dobrym pomysłem programowe restartowanie timera, jeśli ma on odliczać stałe odcinki czasu.
    A to, co zrobiłeś, działa prawdopodobnie dzięki temu, że preskaler się sam nie restartuje.
  • #8 13185624
    tomeeh
    Poziom 24  
    BlueDraco napisał:
    A to, co zrobiłeś, działa prawdopodobnie dzięki temu, że preskaler się sam nie restartuje.


    To brzmi nawet dość logicznie.

    Chociaż dzisiaj udało mi się uruchomić tryb symulatora w AVR Studio 4.19 na timerze 1. Wcześniej nie chciało działać (pytałem o to powyżej), a to dlatego, że miałem wybrany Symulator 1 (a nie 2), a jak się wczytać w dokumentację, to Atmel sam przyznaje, że w symulatorze 1 nie zaimplementowano symulacji Timera1!
    No właśnie i co do wersji 4.19, Simulator 2, nie wygląda już tak różowo, gdyż po 4 sekundach łapię błąd około 128 us, co oznacza 2,5 sekundy na dobę. Niby nie wiele, sam kwarc może się o tyle rozjechać, ale jakoś mi to przeszkadza.

    Tak wiec chyba będę musiał do przerwania 40 ms zaprzęgnąć Timer0 z trybem CTC, ale z uwagi na maksymalny preskaler 1024, będę musiał wstawić kwarc 4 MHz. Z Timerem1 poddaję się, bo CTC działa tylko z komparatorem C, a przerwanie mogą wywołać tylko komparatory A oraz B.


    Tak na marginesie, nie mogę przekonać Symulatora 2, aby pracował z zegarem innym niż domyślne 1 MHz. Może komuś się udało to zmienić? Grzebałem ile się dało w "AVR Simulator 2 Options", ale symulator w ogóle się "nie słucha".


    Update: Udało mi się przekonać Symulator 2 do zmiany częstotliwości. Otóż trzeba zrestartować AVR Studio.
    A co do timerów - ustawiłem tym razem Timer0, dzielnik 1024 (bo większego nie ma) i tryb CTC. Teraz nie trzeba zerować licznika ręcznie - odbywa się to sprzętowo. W mojej aplikacji jest tylko teraz taki minus, że przerwanie mam 2x częściej. Pozostaje programowe zignorowanie co drugiego przerwania, bądź zmniejszenie kwarcu do 4 MHz. Szkoda, że Timer1 nie potrafi generować przerwania w trybie CTC...
  • #9 13205298
    _pieczas
    Poziom 12  
    Podłącze się do tematu gdyż nie chcę zakładać nowego wątku.

    Mam timer (ATMEGA32) ustawiony w taki sposób

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Procedura obsługi przerwania zawiera funkcje komunikacyjne i zwiększa licznik.
    Problem polega na tym, że z wzoru podanego w nocie katalogowej dla trybu CTC częstotliwość przerwań winna wynosić f=fosc/(2N(1+OCR))
    W moim przypadku wynosi to:16000000/(2*256*(1+38)) = 801 Hz.
    Jednak obserwując tempo zwiększania licznika oraz chociażby zmianę stanu diody podczas każdorazowego wywołania obsługi przerwania widać że częstotliwość jest dwukrotnie większa. W przerwaniu timera próbkuje sygnał 50Hz i każdy okres sygnału zawiera 32 próbki co jest jednoznacznym dowodem na częstotliwość timera jako 2*801 Hz.
    Rzeczą pewną jest iż to nieporozumienie leży po mojej stronie, pewnie coś ważnego przeoczyłem. Istotne dla mnie jest samo działanie a nie dowód teoretyczny jednakże interesuje z czego to wynika? Czy ma ktoś pomysł gdzie błądzę w moim rozumowaniu?
  • #10 13205316
    Konto nie istnieje
    Poziom 1  
REKLAMA