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

Attiny2313 - jak poprawnie obsłużyć przerwania w Bascom?

Youngster PL 25 Mar 2008 20:37 2385 24
REKLAMA
  • #1 4953790
    Youngster PL
    Poziom 10  
    Posty: 24
    Witam!
    Zrobiłem urządzonoko na uC Attin2313, które po naciśnięciu jednego przycisku zaświeca kolejno diody na porcie B; po pewnych bólach udało mi się. Teraz próbuje zrobić to samo lecz z wykorzystaniem przerwań... i mam małe kłopoty, a mianowicie napisałem sobie programik w Bascom'ie:

    
    $regfile = "ATtiny2313.dat"
    $crystal = 4000000
    $baud = 9600
    Dim A As Byte
    Config Portb = Output
    Config Portd = Input
    Config Int0 = Falling
    
    A = 1
    
    Enable Interrupts
    Enable Int1
    On Int1 Adding
    
    Do
    If A > 4 Then
    A = 0
    End If
    
    If A = 4 Then
    Portb = &B01111111
    
    End If
    
       If A = 3 Then
       Portb = &B11011111
    
       End If
    
          If A = 2 Then
          Portb = &B11101111
    
          End If
    
             If A = 1 Then
             Portb = &B10111111
    
             End If
    Loop
    
    Adding:
    Disable Interrupts
    A = A + 1
    Waitms 30
    Return
    
    End
    

    W symulatorze wszystko śmiga, po kolei zmienia się stan portów wraz ze wzrastającą wartością zmiennej(jeżeli wystąpi przerwanie), potem zmienna sie zeruje i od początku; lecz gdy programik załaduje do procka to już nie jest tak kolorowo. Procek automatem zwiększa zmienną A i następuje zmiana stanu portu. Wygląda to tak jakby uC symulował sobie przerwanie.

    PS. Po kilkukrotnych resetach procesora raz udało mi się doprowadzić do tego, że kod działał jak należy (po przerwaniu następowała zmiana stanu portu), lecz potem znowu coś się popsuło.
  • REKLAMA
  • #2 4954775
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witaj.
    Tak mi się wydaje, że przerwanie wykona Ci się tylko raz, bo w jego obsłudze blokujesz wszystkie przerwania i już ich więcej nie uaktywniasz. W związku z tym Twój program zapala Ci diodę podłączoną do 6-tego bitu. I koniec na tym. Odblokuj przerwania przed wyjściem z obsługi przerwania. Powinno pomóc.
    Pozdrowienia - teedd
  • REKLAMA
  • #3 4954864
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    @ teedd nieznajomość asemblera się kłania... Niestety nie da się znać samego bascoma jak się chce wiedzieć co on robi...
    Jeśli jest sprzętowy skok do procedury przerwania to na końcu jest return (co jeśli piszesz w bascomie on tłumaczy jako RETI (o ile to jest procedura obsługi przerwania!) )... Czyli return 'n' enable interrupts;)
  • Pomocny post
    #4 4955085
    SteveY
    Poziom 11  
    Posty: 56
    Pomógł: 2
    Nie wiem czy to może coś mieć do rzeczy ale konfigurujesz przerwanie na porcie Int0 na falling a potem obsługujesz przerwanie od Int1.

    Przy resecie jak nic nie ustawiasz to przerwania zewnętrzne są aktywne stanem niskim. Jak nie ustawiasz Int1 na falling a potem pozwalasz na przyjmowanie przerwania z Int1 to możliwe, że wciśnięcie guzika powoduje kilkakrotne wywołanie tego przerwania bo nawet krótkie przytrzymanie go daje dość długi stan niski oczami procka. Może takie coś?
  • #5 4955124
    teedd
    Poziom 19  
    Posty: 219
    Pomógł: 24
    Ocena: 2
    Witam.
    Balu napisał:
    @ teedd nieznajomość asemblera się kłania...Czyli return 'n' enable interrupts;)

    Chylę czoła - nie wiedziałem o tym. Sprawdzę w dokumentacji.
    Pozdrowienia - teedd
  • #6 4956086
    Youngster PL
    Poziom 10  
    Posty: 24
    Dzięki SteveY za twoją uwagę. Przeoczyłem to....pokombinuje, dam znać :D

    PS. jescze takie pytanko: czym różnią się opcje Falling, Rising i Low Level przy konfigurowaniu przerwania od siebie, bo doczytałem się paru różnych wyjaśnień?
  • #8 4956677
    Youngster PL
    Poziom 10  
    Posty: 24
    No tego sie domyśliłem...ale gdzieś przeczytałem, że różni sie to tylko tym iż przy wartości Low Level, gdy następuje polaryzacja nóżki przerwania np. Int1 to wykonuje się ono cały czas (ciągle się powtarza do momentu oderwania napięcia od pinu przerwania). A dla Risingi i Falling spolaryzowanie nóżki przerwania spowoduje aktywację przerwania tylko raz.
  • REKLAMA
  • #9 4956685
    SteveY
    Poziom 11  
    Posty: 56
    Pomógł: 2
    Jak masz ustawione na Low Level i trzymasz nóżkę na poziomie low to przerwanie wykonuje się w kółko, dopóki nie zmieni się stan na wysoki.

    W przypadku zboczy przerwanie wykonuje się tylko na zboczu - opadającym, rosnącym, lub dowolnym (jest taka opcja też do wyboru).

    Czyli tak jak napisałeś :)
  • #10 4957430
    Youngster PL
    Poziom 10  
    Posty: 24
    Aaa...takie buty....:D Dzieki za wyjaśnienie sytuacji. A co do głównego wątku to udało mi się osiągnąć częściowo mój cel, bo program działa tak jakby odwrotnie...mianowicie, gdy zaczynam zasilać uC to procek po kolei ustawia stany portów:
    Portb = &B10111111
    Portb = &B11101111
    Portb = &B11011111
    Portb = &B01111111
    (i tak w kółko)
    Jak nastąpi przerwanie to całość się zatrzymuje. A chciałbym żeby było odwrotnie tzn. dopiero jak wystąpi przerwanie powinno zmieniać stan portów.
    Aktualny kod:
    
    $regfile = "ATtiny2313.dat"
    $crystal = 4000000
    $baud = 9600
    Dim A As Byte
    Config Portb = Output
    Config Portd = Input
    Config Int1 = Low Level
    
    A = 1
    
    Enable Interrupts
    Enable Int1
    On Int1 Adding
    
    Check:
    Do
    If A > 4 Then
    A = 0
    End If
    
    If A = 4 Then
    Portb = &B01111111
    
    End If
    
       If A = 3 Then
       Portb = &B11011111
    
       End If
    
          If A = 2 Then
          Portb = &B11101111
    
          End If
    
             If A = 1 Then
             Portb = &B10111111
    
             End If
    Loop
    
    Adding:
    Disable Interrupts
    A = A + 1
    Waitms 30
    Return
    
    End
    


    Liczę na to, że ktoś mi pomoże. Pozdrawiam !
  • REKLAMA
  • #14 4957717
    Konto nie istnieje
    Konto nie istnieje  
  • #15 4957726
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    Ogólnie rzecz biorąc masz podciąganie wbudowane i myślę, że bascom to automatycznie podciąga, ale nie zaszkodzi ręcznie ustawić portd.0 (czy jaki to tam ma ten tinny) na 1:)
  • #16 4957933
    Youngster PL
    Poziom 10  
    Posty: 24
    Ach Chorwat.....cały czas jest tak samo... próbowałem ręcznie podciągać i ustawiać wartość pin'u przerwania na 1 i na 0, nawet zmieniłem przerwanie na Int0... myślę, że po prostu Bascom albo Attiny tu wysiada :cry:; chyba czas sie przesiąść na C albo Asm'a...oj będzie ciężko.

    Pomimo tego wciąż liczę na cud :D, że ktoś wymyśli coś co mi pomoże.
  • #17 4958046
    Balu
    Poziom 38  
    Posty: 4397
    Pomógł: 323
    Ocena: 48
    W kwestii formalnej:
    Adding:
    Disable Interrupts
    tutaj disable interrupts Sobie daruj... i tak nic nie zmienia...

    Teraz tak, nie obrażaj Pan bascoma bo na nim robią ludzie na prawdę poważne projekty... a to jest żart a nie projekt :)

    Dalej, nie pisałeś nigdzie jakim poziomem sterujesz przycisk, masz gdzieś usuwanie drgań sprzętowe? Jak nie to zrób softwareowe.... chyba, że jesteś magikiem i problem drgań Cię nie dotyczy... Może 30ms to za mało?
    Kolejna rzecz w przerwaniach NIE UMIESZCZAMY opóźnień. Jak się teraz tak nauczysz, później będzie pokutowało...
    I ustaw odpowiedni PORTprzerwania.PINprzerwania na 1 po konfiguracji przerwań a przed zezwoleniem na przerwania globalne.
  • #18 4958226
    Youngster PL
    Poziom 10  
    Posty: 24
    1. Zwracam honor Bascom'owi :D
    2. Wiem, że ten kodzik nie jest super hiper pro. Pro Bascom koderzy napisali by taki coś pewnie w 5 min i zupełnie inaczej
    3. Mój przycisk to dwa kabelki podłączone do VCC i GND, którymi próbuje spolaryzować piny.
    4. Usuwanie drgań no hm...eh....nie za bardzo wiem jak to tu zrealizować
    5. Co do opóźnień w przerwaniach to przyswoiłem radę :D
  • #20 4958517
    Youngster PL
    Poziom 10  
    Posty: 24
    Nie zwieram.... źle to zabrzmiało... po prostu podłączam kabelkiem dany pin, na którym zdefiniowałem wejście do VCC albo do GND i ustalam przy której polaryzacji działa jak należy.

    Jutro napisze kod na spokojnie biorąc pod uwagę wszystkie rady:D
  • #21 4958740
    SteveY
    Poziom 11  
    Posty: 56
    Pomógł: 2
    Myślałem, że z tym przyciskiem to jednak coś wymyśliłeś:)

    Problem w tym, że jak wciskasz guzik to to nie jest tak ładnie jak nam się wydaje, że wciskasz i się zmienia stan. Przycisk się trochę 'odbija' ale w takim tempie, że procek wykrywa to odpięcie i zapięcie.

    Polecam zgooglać sobie hasło 'debouncing' i zastosować się do jakiejś rady. Najlepiej chyba przy wykryciu stanu '0' przy guziku podpiętym do jakiegoś pinu z jednej i GND z drugiej strony po jakimś czasie zobaczyć czy znowu jest zero i jak tak to wtedy przyjąć, że guzik został wciśnięty.

    Można też to robić sprzętowo ale nie wiem czy Ci się chce bawić. Ja, jak robiłem matrycową klawiaturkę, w momencie wykrycia gdzieś '0' po prostu ustawiałem piny 'źródłowe' znowu na '1', żeby nic już nie wykryć więcej. Działało dobrze. Tutaj możesz zrobić tak samo, podpinając guzik między jednym pinem ustawionym na out i nadającym 0 i drugim pinem zdefiniowanym na in.

    W momencie wykrycia '0' na pinie in ustawiasz '1' na porcie out i obsługujesz wciśnięcie guzika, wstawiasz jakieś opóźnienie i znowu robisz '0' na out. Ale generalnie polecam google bo metod jest masa :)
  • #22 4977577
    Youngster PL
    Poziom 10  
    Posty: 24
    Witam!
    Pare dni mnie nie było na forum z paru przyczyn technicznych jak i innych (spr. z maty):D. W ten weekend udało mi się naskrobać stabilną(przynajmniej dla moich warunków) wersję tego mojego programu :D:
    
    $regfile = "ATtiny2313.dat"
    $crystal = 4000000
    $baud = 9600
    Dim A As ByteConfig Portb = Output
    Config Portd = Input
    Config Int1 = Low Level
    A = 1
    Enable Interrupts
    Enable Int1 Nosave
    On Int1 Ink:
    
    Do
    Select Case A
    Case 1 : Portb = &B11011111
    Case 2 : Portb = &B11101111
    Case 3 : Portb = &B10111111
    Case 4 : Portb = &B01111111
    Case 5 : A = 1
    End Select
    Loop
    
    Ink:
    A = A + 1
    Waitms 30
    Return
    End
    


    PS. Co do rad Balu, o opóźnieniach w przerwaniach to niestety musiałałem dać opóźnienia właśnie tam, bo jak dałem w zwrotnicy case to sie program sypał (przynajmniej u mnie się tak dzieje).

    Dzięki wszystkim za pomoc!:D
  • #23 4977780
    Konto nie istnieje
    Konto nie istnieje  
  • #24 4977993
    Youngster PL
    Poziom 10  
    Posty: 24
    Niestety ja nie wiem kolego.... nie jestem (jeszcze) takim PRO w sprawach mikrokontrolerów :D

Podsumowanie tematu

✨ Dyskusja dotyczy poprawnej obsługi przerwań w mikrokontrolerze ATtiny2313 programowanym w Bascom. Autor opisuje problem z implementacją przerwań, gdzie przerwanie wykonywało się tylko raz z powodu wyłączania globalnych przerwań w procedurze obsługi i braku ich ponownego włączenia. Zwrócono uwagę na konieczność odblokowania przerwań przed zakończeniem ISR oraz na poprawne skonfigurowanie przerwania (np. Int0 vs Int1) i jego trybu (Falling, Rising, Low Level). Omówiono różnice między trybami przerwań: zbocze opadające, narastające oraz poziom niski, gdzie przerwanie na poziomie niskim wykonuje się ciągle, dopóki stan nie zmieni się na wysoki. Poruszono problem drgań styków przycisku (debouncing) i zalecenia, by unikać opóźnień w ISR oraz stosować programowe lub sprzętowe eliminowanie drgań. Sugerowano ręczne ustawienie podciągania pinu przerwania. Autor ostatecznie przedstawił stabilną wersję programu, w której zmienna sterująca stanem portów jest zmieniana w ISR bez wyłączania przerwań, a główna pętla reaguje na jej wartość, co pozwala na zmianę stanu portów tylko po wystąpieniu przerwania. W dyskusji pojawiły się także pytania o różnice w konfiguracji przerwań w mikrokontrolerach AVR z serii mega, gdzie potwierdzono możliwość konfiguracji zbocza przerwania.
Wygenerowane przez model językowy.
REKLAMA