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

[AVR] Nieaktywny Auto Trigger ADC na ATmega168 przy użyciu Timer0 w trybie CTC

robiw 16 Gru 2020 12:44 468 19
REKLAMA
  • #1 19117972
    robiw
    Poziom 26  
    Witajcie,
    Problem powinien być trywialny a nie jest. Dotychczas stosowałem auto trigger ADC na ATtiny13 i działało to przewidywalnie według datasheeta, ale kod przeniosłem na ATmege168 i działać przestało, mimo że wszystko ustawione według dokumentacji. Po krótce:

    - uruchamiam timer0 w trybie CTC by zdarzenie Compare Match A zachodziło co 250us (4kHz),

    - uruchamiam przetwornik ADC, ustawiam mu Auto Trigger Enable i Auto Trigger Source: Timer/Counter0 Compare Match A,

    - w przerwaniu ISR(ADC_vect) "macham" zwyczajnie pinem by sprawdzić, czy wyzwalacz działa...

    i NIE działa. Autotrigger udaje się tylko uruchomić w trybie Free Running, natomiast każdy, inny wyzwalacz nie działa. ATmega168 taktowana kwarcem 16MHz, zasilanie 5V. Kod poniżej:

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


    Obejrzałem też w symulacji na Atmel Studio, czy ustawiane są poszczególne rejestry i wszystko wydaje się być w porządku. Sprawdzane jeszcze na innej Medze48 (tym razem). Też nie działa co oznacza, że gdzieś popełniam błąd. ALE gdzie??? Pozdrowienia... robiw
  • REKLAMA
  • #2 19118086
    ex-or
    Poziom 28  
    Nie jestem pewien, ale coś mi się zdaje, że w trybie CTC zdarzenie Compare Match nie jest generowane.
    Może spróbuj ustawić trigger na overflow.
  • REKLAMA
  • #3 19118111
    robiw
    Poziom 26  
    Puszczałem Timer0 w trybie Normal i autotrigger na Timer0 overflow. Bez zmian. Działą tylko Free Running...robiw

    Dodano po 15 [minuty]:

    ex-or napisał:
    Nie jestem pewien, ale coś mi się zdaje, że w trybie CTC zdarzenie Compare Match nie jest generowane.
    Może spróbuj ustawić trigger na overflow.


    An interrupt can be generated each time the counter value reaches the TOP value by using the OCF0A Flag. If the interrupt is enabled, the interrupt handler routine can be used for updating the TOP value.

    Tyle w temacie... robiw
  • REKLAMA
  • #4 19118302
    ex-or
    Poziom 28  
    Trzeba włączyć przerwanie COMP0A i zdefiniować procedurę obsługi (może być pusta)

    ...
    TIMSK0 = _BV(OCIE0A);
    ...
    EMPTY_INTERRUPT(TIMER0_COMPA_vect)
    ...
  • #5 19118314
    robiw
    Poziom 26  
    Ale po co??? To nie działa od przerwania a od zdarzenia. Nie ma potrzeby deklaracji przerwania...robiw

    PS. Przynajmniej według dokumentacji nie ma takiej potrzeby. W przypadku ATtiny13 działało bez ISR timera...robiw
  • REKLAMA
  • #7 19118413
    robiw
    Poziom 26  
    JarekC napisał:
    A kasujesz flagę OCF0A, bo jeżeli nie to co najwyżej raz ci wyzwoli ADC.
    ADC jest wyzwalany gdy flaga zmienia stan z 0 na 1;


    Gdzie masz taką informację o konieczności kasowania flagi OCF0A? Jeśli tak by było to konieczna byłaby obsługa przerwania Compare Match A tylko po to by wyzwalać ADC co trochę kłóciłoby się z sensownością takiego mechanizmu? W ATtiny 13 nie było takiej potrzeby i działało... robiw
  • #8 19118423
    ex-or
    Poziom 28  
    JarekC napisał:
    A kasujesz flagę OCF0A, bo jeżeli nie to co najwyżej raz ci wyzwoli ADC.

    Słusznie, przerwanie to efekt ustawienia flagi (którą przy okazji kasuje).
  • #9 19118429
    robiw
    Poziom 26  
    Na pewno jest logika w tym, o czy piszecie, ale...nie ma logiki odnośnie samego zdarzenia. Zamysłem automatycznego wyzwalania jest akwizycja sprzętowa a nie programowa. To wyzwalanie ma się odbywać sterowane sprzętowo a dopiero w ISR(ADC_vect) można sobie robić co dusza zapragnie. Z resztą tak to działało w ATtiny13... robiw
  • #11 19118715
    robiw
    Poziom 26  
    Masz na myśli kasowanie flagi zgłoszenia przerwania ADC poprzez wpisanie jedynki na bit flagi? Robiłem na 328P, nie działa. Jutro spróbuję na m168...r

    Dodano po 26 [minuty]:

    W projekcie z ATtiny zdarzenie porównania generuje przerwanie i pewnie tutaj jest "pies pogrzebany". To przerwanie kasuje sprzętowo flagę porównania...ale to bez sensu, żeby angażować przerwanie Timera0 skoro jego porownanie powinno być wyzwalaczem sprzętowym konwersji ADC... Robiw
  • Pomocny post
    #12 19118848
    JarekC
    Poziom 32  
    Masz skasować flagę timera OCF0A
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Możesz też włączyć przerwanie od Timera i zostawić pustą obsługę przerwania:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Co spowoduje że cała obsługa przerwania sprowadzi się do RETI
  • #13 19118885
    trol.six
    Poziom 31  
    robiw napisał:
    i? Robiłem na 328P, nie działa

    A ja na jakimś AVR 328 robiłem i działa. Z tym że używałem T1. Jednak w nocie nie pisze konkretnie o T0 tylko ogólnie o fladze, nawet jest uwaga ze zmiana źródła wyzwalania może wyzwolić ADC. Nie musisz używać przerwań od timera ale skasować flage raczej trzeba.
    robiw napisał:
    An interrupt can be generated each time the counter value reaches the TOP value by using the OCF0A Flag. If the interrupt is enabled, the interrupt handler routine can be used for updating the TOP value.

    Tyle w temacie... robiw


    TOP to nie jest compare tylko overflow. Tak to rozumiem. Zmień to żródło z compare na overflow.

    dodane: Oczywiście przy overflow kasujesz flage overlfow, a przy compare kasujesz falge compare.

    dodane2: w tym trybie CTC, to w ogóle trzaby sprawdzić które przerwanie się generuje bo flaga OCF0A jest od compare a TOP jest od overflow. A osobiście nie pamiętam czy to testowałem w praktyce.
    .
  • #14 19118924
    robiw
    Poziom 26  
    JarekC napisał:
    Masz skasować flagę timera OCF0A


    Wiem, wiem...

    Skasowanie flagi w przerwaniu ADC załatwia temat. Na przyszłość nauczka by słowo w słowo czytać datasheety. No i logika jakaś potrzebna. Skoro wystąpiło zdarzenie Compare Match A to stosowna flaga jest ustawiona. Występuje zdarzenie rising dla ustawionego triggera, które wyzwala konwersję ADC. Nie mamy przerwania od timera, które kasowałoby flagę, więc dopóki nie skasujemy flagi ręcznie w przerwaniu ADC (TIFR0 = (1<<OCF0A);) to nie wystąpi kolejne zdarzenie rising, które wyzwoliłoby kolejną konwersję ADC. Wszystko logiczne. Dzięki JarekC... robiw
  • #16 19118974
    robiw
    Poziom 26  
    Przeca o tym piszę powyżej...r
  • #18 19119028
    robiw
    Poziom 26  
    Działa, działa, jak najbardziej. Napisałem o tym powyżej. Z suma logiczna dla flagi czy bez to bez znaczenia, bo flagę kasuje w ISR...robiw
  • #19 19119055
    ex-or
    Poziom 28  
    robiw napisał:
    Z suma logiczna dla flagi czy bez to bez znaczenia,

    Przeciwnie, ma to ZASADNICZE znaczenie
    robiw napisał:
    bo flagę kasuje w ISR

    W tym przypadku (tj. flag gaszonych 1) zachowanie atomowości operacji RMW jest bez znaczenia

Podsumowanie tematu

Użytkownik napotkał problem z automatycznym wyzwalaniem przetwornika ADC na ATmega168 przy użyciu Timer0 w trybie CTC. Mimo poprawnej konfiguracji, auto trigger działał tylko w trybie Free Running. W dyskusji zasugerowano, że konieczne jest skasowanie flagi OCF0A, aby umożliwić kolejne wyzwolenia ADC. Użytkownicy podkreślili, że brak kasowania flagi prowadzi do braku narastającego zbocza, co uniemożliwia wyzwolenie konwersji. Wskazano również, że w przypadku ATtiny13 nie było potrzeby używania przerwań, co różni się od ATmega168. Ostatecznie, rozwiązaniem było ręczne kasowanie flagi w przerwaniu ADC, co pozwoliło na prawidłowe działanie automatycznego wyzwalania.
Podsumowanie wygenerowane przez model językowy.
REKLAMA