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

[Atmega32A][asm] Jak uruchomić timer do wyłączania diod po 0,5s?

24 Lis 2018 14:57 1035 12
REKLAMA
  • #1 17582110
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #2 17582153
    excray
    Poziom 41  
    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
  • #3 17582310
    Konto nie istnieje
    Poziom 1  
  • Pomocny post
    #4 17582514
    Andrzej__S
    Poziom 28  
    werbatyna napisał:
    Kod: AVR assembler
    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: AVR assembler
    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.
  • REKLAMA
  • #5 17582515
    Konto nie istnieje
    Poziom 1  
  • #6 17582853
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #7 17582975
    Andrzej__S
    Poziom 28  
    werbatyna napisał:
    Kod: AVR assembler
    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.
  • REKLAMA
  • #8 17583160
    Konto nie istnieje
    Poziom 1  
  • #9 17583332
    Andrzej__S
    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: AVR assembler
    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.
  • #10 17583369
    Konto nie istnieje
    Poziom 1  
  • #11 17583962
    Andrzej__S
    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: AVR assembler
    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: AVR assembler
    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.
  • #12 17593703
    Konto nie istnieje
    Poziom 1  
  • #13 17594261
    trol.six
    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.
    .
REKLAMA