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

[Atmega32A][asm] - Timer nie uruchamia się

24 Lis 2018 14:57 603 12
  • Poziom 3  
    Witam,
    Chciałabym zrobić obsługę timera, aby wszystkie diody po przyciśnięciu przycisku się włączały, a po upływie czasu ok. 0,5 sekundy się wyłączały. Niestety timer w kodzie mojego programu nie uruchamia się i nie wiem czym to jest spowodowane.

    Kod: avrasm
    Zaloguj się, aby zobaczyć kod
  • Poziom 39  
    Może dlatego, że wchodząc w przerwanie zapisałaś SREG w r20 a wychodząc z niego odtworzyłaś SREG z zawartości r22:
    werbatyna napisał:
    in R20, SREG
    .
    .
    .
    out SREG, R22
    reti
  • Poziom 3  
    Pomyliłam się przy wklejaniu kodu, w programie mam dobrze czyli R20, więc to nie w tym jest problem.
  • Pomocny post
    Poziom 28  
    werbatyna napisał:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    Załóżmy, że to też błąd przy wklejaniu kodu (inaczej asembler zgłosiłby błąd). Powinno być R21, a nie R121.

    werbatyna napisał:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    Być może to też błąd przy wklejaniu. Bity WGM12, CS12 oraz CS10 nie znajdują się w rejestrze TCCR1A tylko w TCCR1B.

    Istotne jest jednak to, że ustawiając tylko bit WGM12 ustawiasz TIMER1 w tryb 4, czyli tryb CTC, w którym timer liczy od 0 do wartości MAX zawartej w rejestrze OCR1A. Ty do tego rejestru nic nie wpisujesz, a po załączeniu zasilania (po Power-on reset) jego wartość wynosi 0. Timer zlicza więc od 0 do 0, a wartość OCR1B, przy której następuje przerwanie, jest dużo większa, więc przerwanie nigdy nie wystąpi. Pomiń ustawianie bitu WGM12 lub wpisz do OCR1A wartość większą od OCR1B.

    Dodatkowy problem jest taki, że w przerwaniu od timera dobrze byłoby go wyłączyć (np. poprzez wyzerowanie bitów CS12 i CS10), bo po pierwszym naciśnięciu przycisku przerwanie będzie występować na okrągło nawet, jak przycisk nie zostanie naciśnięty. Przy tak prostym programie to może nie ma znaczenia, ale kiedy zostałby nieco rozbudowany, cykliczne zerowanie PORTA może nie być pożądane.

    Podobnie może być z drganiami styków. Przy tym kodzie może będzie to niezauważalne, jednak trzeba wziąć pod uwagę, że ze względu na drgania styków procedura obsługi przerwania int_ext może wykonać się kilkakrotnie, co (w przypadku innego kodu) może powodować problemy.

    To tyle, co zauważyłem. Nie mogę całkowicie wykluczyć innych błędów.
  • Poziom 1  
  • Poziom 3  
    Tak wygląda teraz mój kod, dodałam jeszcze czyszczenie flagi żądania z rejestru GIFR, jednak z tego co widzę na symulatorze timer dalej nie wykonuje się.
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod
  • Poziom 28  
    werbatyna napisał:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    Czy to oznacza, że przycisk masz podłączony pod pin 0 portu B?
    Wejście INT0 w ATmega32 jest na pinie 2 portu D i tam powinien być podłączony przycisk, aby wywołać przerwanie. Dopiero procedura obsługi tego przerwania włącza timer 1.
  • Poziom 3  
    Tak, przycisk mam tak podłączony, aby nie zrobić zwarcia podłączając przycisk pod przerwanie INT0 . Dlatego podpinam przerwanie INT0 do złacza JP13, a przycisk z portu B do klawiatury. Procedura przerwania wykonuje się w programie, jednak nie wykonuje się timer. Być może nie można tego sprawdzić w symulatorze, a niestety nie mam w tej chwili możliwości sprawdzenia tego na mikrokontrolerze.
  • Poziom 28  
    werbatyna napisał:
    Tak, przycisk mam tak podłączony, aby nie zrobić zwarcia podłączając przycisk pod przerwanie INT0 .

    Nie rozumiem, dlaczego miałabyś zrobić zwarcie. Po załączeniu zasilania wszystkie piny mikrokontrolera są ustawione jako wejścia, a Ty nie zmieniasz konfiguracji pinu 2 portu D na wyjście, więc tam zwarcia żadnego być nie może.

    werbatyna napisał:
    Dlatego podpinam przerwanie INT0 do złacza JP13, a przycisk z portu B do klawiatury.

    Nie wiem co to jest JP13 czy też jaką płytką dysponujesz. Możesz narysować, jak to wszystko masz podłączone? Albo chociaż jakiś schemat płytki? ...bo obawiam się, że masz podłączone nieprawidłowo. W programie powinno być ustawione podciąganie pinu 2 portu D do Vcc:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    natomiast przycisk powinien być podłączony pomiędzy pin 2 portu D a masę. Podłączając przycisk pod PORTB nie wywołasz przerwania INT0.

    werbatyna napisał:
    Procedura przerwania wykonuje się w programie, jednak nie wykonuje się timer.

    Na jakiej podstawie tak twierdzisz? Jeśli masz w programie włączone generowanie przerwania INT0, a pin INT0 (czyli pin 2 portu D) nie jest podłączony do niczego, to w rzeczywistym układzie wywołanie przerwania może nastąpić w wyniku zakłóceń spowodowanych stanem nieustalonym na pinie, ale nie pod wpływem naciśnięcia przycisku. W symulatorze na pewno nie wywołasz przerwania INT0 zmieniając stan pinu 0 portu B.

    Reasumując, aby można było Ci pomóc musisz pokazać schemat.

    werbatyna napisał:
    Być może nie można tego sprawdzić w symulatorze, a niestety nie mam w tej chwili możliwości sprawdzenia tego na mikrokontrolerze.

    Akurat program, który przedstawiłaś, można sprawdzić w symulatorze.
  • Poziom 3  
    [Atmega32A][asm] - Timer nie uruchamia się

    Tak wygląda połączenie na mojej płytce, nie jest to schemat, ale wydaje mi się, że można z niego odczytać dobrze połączenie.
  • Poziom 28  
    No właśnie z tego niewiele wynika, bo nie widać dobrze połączeń (ścieżek) pomiędzy poszczególnymi elementami płytki, ale zakładam, że to zestaw uruchomieniowy ZL3AVR.

    W takim przypadku proponuję usunąć połączenie PB0 (JP16) z W1 (JP23), bo w tym przypadku będzie niepotrzebne.
    W programie należałoby zmienić:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    Spowoduje to podciągnięcie do Vcc poprzez wewnętrzny rezystor pull-up pinu PD2 (INT0).
    Dzięki tym zmianom pin INT0 nie będzie w stanie nieustalonym, a wciśnięcie dowolnego przycisku z kolumny 1 (czyli S1, S5, S9 lub S13) powinno spowodować wywołanie przerwania.

    Następna sprawa - wywołanie przerwania INT0 masz skonfigurowane na zbocze narastające, natomiast korzystając z podłączenia INT0 ze złączem JP13 (Klawisz wciśnięty), wciśnięcie klawisza spowoduje powstanie zbocza opadającego, a dopiero puszczenie wywoła zbocze narastające, które uruchomi przerwanie. Jeśli chcesz wywołać przerwanie zaraz po naciśnięciu (a nie dopiero po puszczeniu klawisza) usuń z kodu linijkę:
    Kod: avrasm
    Zaloguj się, aby zobaczyć kod

    Tutaj jednak pojawia się dodatkowy problem, o którym wspominałem wcześniej, czyli drgania styków. Mogą one nawet spowodować, że przerwanie będzie wywołane zarówno po wciśnięciu, jak i po zwolnieniu klawisza i zerowanie flagi pod koniec obsługi przerwania INT0 niewiele tu pomoże (generalnie obsługa klawiatury za pomocą przerwań zewnętrznych to nie najlepszy pomysł). Dobrze byłoby to sprawdzić w ten sposób:
    • wcisnąć klawisz i nie puszczać do czasu, kiedy timer wyłączy diody,
    • puścić klawisz i zaobserwować reakcję diod.

    Można ewentualnie spróbować wyeliminować problem stosując sprzętowy debouncing.

    Twój kod sprawdziłem w symulatorze i po wprowadzeniu proponowanych zmian powinien działać prawidłowo (teoretycznie, nie uwzględniając problemów związanych z drganiami styków). Opóźnienie będzie (z grubsza) prawidłowe pod warunkiem, że taktowanie mikrokontrolera wynosi 4MHz.
  • Poziom 3  
    Jeszcze mam jedną wątpliwość z czyszczeniem flagi z rejestru GIFR. Powinno się to odbywać tak jak teraz i w przerwaniu i w timerze, czy jednak skoro flaga GIFR powinna się czyścić automatycznie w procedurze przerwania to trzeba ją czyścić tylko w timerze?
  • Poziom 31  
    W takim przypadku czyszczę flagi przed włączeniem przerwania (choć to zależy od konstrukcji programu i co ma robić i jak reagować ), natomiast w przerwaniu wyłączam przerwanie. Ponieważ jeśli nie masz dobrego sprzętowego debouncingu to na wejściu możesz mieć wiele takich impulsów i kilkukrotne wejście do przerwania.

    Nie bez powodu często polecana metoda obsługi przycisków to sprawdzanie ich stanu np co 20ms.
    .