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

[Mega32][BAscom]Dziwne zachowanie przerwań

cyberdar 08 Lip 2010 11:05 2164 6
REKLAMA
  • #1 8273108
    cyberdar
    Poziom 31  
    Witam

    Postanowiłem przetestować wszystkie przerwaniaw ATMEGA32. Program ma działać następująco: naciskam klawisz podpięty pod INT0 (podciągnięty rezystorem 1kom do Vcc) i licznik zlicza mi to naciśnięcie. Naciskam drugi klawisz podpięty pod INT1 (podciągnięty rezystorem 1kom do Vcc) i licznik zlicza mi to naciśnięcie. Teraz jeśli nacisnę klawisz podpięty pod INT2 to na podstawie kolejności wciśniętych klawiszy licznik_2 powinien być incrementowany bądź dekrementowany. Tak się jednak nie dzieje. Jeśli powinien być incementowany to dodaje do licznika_2 2 a jeśli dekrementowany to nic się nie dzieje. Pytanie, dlaczego tak się dzieje ? Program poniżej.

    
        $regfile = "m32def.dat"
       $crystal = 8000000
    
       Config Int0 = Rising : On Int0 Przerwanie_int0
    
       Config Int1 = Rising : On Int1 Przerwanie_int1
    
       Config Int2 = Rising : On Int2 Przerwanie_int2
    
       Config Lcd = 20 * 4
       Config Lcdpin = Pin , Db4 = Portd.5 , Db5 = Portd.4 , Db6 = Portd.1 , Db7 = Portd.0 , E = Portd.6 , Rs = Portd.7
    
       Config Pina.1 = Input : Res Alias Pina.1
    
       Dim Licznik_1 As Byte
       Dim Licznik_2 As Integer
       Dim Kod_oper As Byte
    
       Licznik_2 = 5 : Licznik_1 = 0 : Kod_oper = 0
    
       Cursor Off : Cls
    
       Enable Interrupts : Enable Int0 : Enable Int1 : Enable Int2
    
       Do
       Home Upper
       Lcd "        " ; Licznik_2 ; " m     "
       Waitms 100
       Loop
    
       Przerwanie_int0:
        Disable Int0 : Incr Licznik_1 : If Licznik_1 = 2 Then Kod_oper = 2
       Return
    
       Przerwanie_int1:
        Disable Int1 : Incr Licznik_1 : If Licznik_1 = 2 Then Kod_oper = 1
       Return
    
       Przerwanie_int2:
        Disable Int2
    
        Select Case Kod_oper
    
         Case 0 : Licznik_1 = 0
                   Kod_oper = 0
    
         Case 1 : Incr Licznik_2
                   Licznik_1 = 0
                    Kod_oper = 0
    
         Case 2 : Decr Licznik_2
                   Licznik_1 = 0
                    Kod_oper = 0
    
         Case 3 To 255:Licznik_1 = 0
                   Kod_oper = 0
    
        End Select
    
         Enable Int0
          Enable Int1
           Enable Int2
    
       Return
    
    


    pozdrawiam,
    cyberdar
  • REKLAMA
  • #2 8273537
    szelus
    Poziom 34  
    Czy to blokowanie przerwań w odpowiedniej procedurze obsługi to w celu eliminacji drgań styków? Jeżeli tak, to dla przycisku 2 nie jest to poprawnie - zarówno naciśnięcie jak i puszczenie ma prawo wygenerować zbocze narastające, a nawet kilka.
  • REKLAMA
  • #3 8273569
    cyberdar
    Poziom 31  
    Witam

    Blokowanie jest konieczne bo mogą wystąpić tylko dwa zdarzenia (po jednym dla każdego przerwania INT0 i INT1). W obsłudze przerwań (INT0 i INT1) ustalana jest kolejność naciśnięcia klawiszy natomiast INT2 ma spowodować dodanie lub odjęcie (o jeden !) wartości licznika_2. Dodam dodatkowo, że problem ma być rozwiązany na przerwaniach a nie jak by to miało miejsce normalnie na portach.

    --
    pozdrawiam
  • REKLAMA
  • #4 8273618
    szelus
    Poziom 34  
    Ok, czyli efektów powodowanych przez drgania styków wcale nie uwzględniłeś w programie. Dobrze zrozumiałem?
    Każdy mechaniczny styk w momencie przełączenia, na skutek drgania (sprężystości) styku generuje kilka załączeń/rozłączeń. Musisz to uwzględnić w programie i odfiltrować. Przeszukaj sobie elektrodę pod hasłem "drgania styków".
  • #5 8273656
    cyberdar
    Poziom 31  
    Witam.
    Jak program wejdzie raz do obsługi przerwania to je wyłącza. Czyli eliminacja drgań styków jest załatwiona. Przynajmniej w przypadku INT0 i INT1. I to chodzi dobrze. Teraz jak wejdzie do obsługi przerwania INT2 to wyłącza je, dokonuje inkrementacji /dekrementacji zmiennej, kasuje zmienne, włącza przerwania (INT0, INT1) i wyskakuje z przerwania. I w tym wypadku nawet jeśli wszedłby do obsługi przerwania przez drgania styków to ma już wszystkie dane wykasowane do tego aby dalej zliczać.

    --
    pozdrawiam


    PS
    Zrobiłem jeszcze jedną próbę. Mianowicie przerwanie INT2 jest włączane przerwaniem INT0 lub INT1. Czyli jak wejdzie raz do niego to pomimo drgań styków i tak nie będzie mogło wejść po raz kolejny. A działa tak samo źle !!!
  • REKLAMA
  • #6 8279183
    ZbeeGin
    Poziom 39  
    cyberdar napisał:
    Jak program wejdzie raz do obsługi przerwania to je wyłącza. Czyli eliminacja drgań styków jest załatwiona.

    Otóż nie jest załatwiona. Nawet jak wyłączysz przerwania na początku to i tak nie wyłączysz ich bezpośrednio po przyjęciu przerwania, a dopiero po paru mikrosekundach jak 28 rejestrów poleci na stos.
    W tym czasie może zostać zgłoszone następne przerwanie z drgania styku, którego flaga będzie "wisieć" przez cały czas, do momentu włączenia przerwania. Jak odblokujesz przerwania to procesor zauważy pozostawioną aktywną flagę i przerwanie zostanie zgłoszone - a przecież nie naciskałeś klawisza!
  • #7 8280385
    janbernat
    Poziom 38  
    Czyli na końcu obsługi przerwania można wpisać:
    Set GIFR.intfx - gdzie x- numer przerwania.
    Bo to jest tak że rejestr w którym wpisujemy zezwolenie na obsługę przerwania to nie jest ten sam rejestr do którego jest zgłaszana flaga wystąpienia przerwania.
    Ten pierwszy Bascom obsługuje sam- przez enable.
    A do drugiego trzeba się "dogrzebać" ręcznie.
    Pacaneum to nie jest- zawsze może się zdarzyć że w czasie zdejmowania ze stosu ta flaga się pojawi.
    Ale pomaga.
REKLAMA