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.

Przerwania - Jak wyłączyć?

28 Gru 2007 22:00 1531 8
  • Poziom 20  
    Witam :)

    Mam następujący problem.

    Jak podczas obsługi przerwania lub podczas trwania programu sprawić aby chwilowo wyłączyć przerwania.
    Np aby podczas obsługi jednego przerwania nie zostało wykonywane inne przerwanie.



    [......]

    ISR(INT0_vect) // przerwanie wywołane wciśnięciem przycisku
    {
    cli();
    [.......] // kod przerwania
    sei();
    }
    mimo takiego zpisu podczas wykonywania kodu przerwania inne przerwania nie zostają wyłączone, a podczas szybkiego wciskania przycisku przerwanie zanim zakończy się zostaje wywoływane ponownie.
    Jak temu zaradzić?

    dziękuje
    Darmowe szkolenie: Ethernet w przemyśle dziś i jutro. Zarejestruj się za darmo.
  • Poziom 11  
    Miałem kiedyś podobne problemy i może chodzić o kasowanie flagi przerwania. Ja w Atmega8 po prostu kasowałem tę flagę przez wpisanie 1 do całego rejestru na końcu przerwania i problem zniknął:

    GIFR=0xff;
  • Poziom 20  
    bogo88 napisał:
    Miałem kiedyś podobne problemy i może chodzić o kasowanie flagi przerwania. Ja w Atmega8 po prostu kasowałem tę flagę przez wpisanie 1 do całego rejestru na końcu przerwania i problem zniknął:

    GIFR=0xff;


    niestety problem nadal sie pojawia.. Można prosić o szerszy komentarz?

    w katalogu znalazłem coś na temat rejestru GIFR i bicie INTF0

    "Bit 6 – INTF0: External Interrupt Flag 0
    When an event on the INT0 pin triggers an interrupt request, INTF0 becomes set (one). If the Ibit
    in SREG and the INT0 bit in GICR are set (one), the MCU will jump to the corresponding
    Interrupt Vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag
    can be cleared by writing a logical one to it. This flag is always cleared when INT0 is configured
    as a level interrupt."

    niestety nie rozumiwe wszystkiego po angielsku ale wydaje mi sie że nia ma to raczej związku z problemem.

    Dlaczego samo cli(); nie wystarcza?
  • Pomocny post

    Poziom 26  
    Jak nie zostaje wyłączone... Przecież podczas wykonywania przerwania inne są automatycznie blokowane, właśnie poprzez wyzerowanie globalnej obsługi przerwań - tak więc nie ma nawet potrzeby stosowania specjalnych zabiegów (cli) w tym celu, to właśnie żeby włączyć stosuje się sei w przypadku, gdy trzeba odblokować przerwanie tak, aby możliwe było jego wykonianie jeszcze w trakcie obsługi innego przerwania. Swoją drogą nie wiem co ty robisz w tym przerwaniu, że jego obsługa trwa aż tyle, że mechanicznie zdążysz kolejny raz wcisnąć przycisk - przecież to aż ułamek sekundy, kilkaset tysięcy taktów... Zajmujące dużo czasu procedury należy generalnie przenosić poza przerwanie i korzystać ze zmiennych globalnych wskazujących na fakt wystąpienia przerwania, a później jakaś pętelka sprawdzajaca regularnie stan zmiennej i odpowiednio reagująca, dzięki temu nie blokuje się przerwania, choć u ciebie to akurat nawet w drugą stronę chcesz zrobić - żeby nie przejmować się blokowaniem, tylko właśnie podtrzymywać to. Coś musi być źle napisana ta obsługa przerwania, podałeś taki ogólnikowy przykład, może więcej szczegółów... Kiedyś były, owszem, dwa sposoby ( SIGNAL i INTERRUPT) teraz INTERRUPT uznane jest za przestarzałe i jest SIGNAL, czyli ISR (INTERRUPT = SIGNAL + sei, więc nie ma potrzeby dwóch, w razie czego ręcznie się odblokowuje, a wprowadzało tylko zamieszanie) trochę w helpie avr-libc-user-manual o tym znajdziesz.
  • Poziom 32  
    TO poprostu na poczatku przerwania INT0 wylącz przerwanie od INT0 i po krzyku.
  • Poziom 12  
    Z tego co widzę piszesz w C.
    masz dwie funkcje na obsługę przerywania
    INTERRUPT oraz SIGNAL
    któraś z nich pozwala na obsłużenie przerywania podczas obsługi jej a druga blokuje przerywania.

    PS. Chyba funkcja SIGNAL będzie dla ciebie odpowiednia.
    PS2. wszystko zależy również od kompilatora jakiego używasz ja pisze w avrgcc

    Pozdrawiam.
  • Specjalista - Mikrokontrolery
    Petros napisał:
    chodziło o to że na wejście INT0 podany był zakodowany sygnał i chodziło tylko o to aby jego pierwszy bit wywołał przerwanie.

    dziękuje


    Jeśli potrzebujesz przerwania tylko na pierwszym zboczu ramki i wszystkie pozotałe bity tej ramki odczytujesz właśnie w tym jednym przerwaniu to problem jest tylko w tym że kolejne przychodzące zbocza ustawiają flagę przerwania od INT podczas trwania tego przerwania. Gdy wychodzisz z przerwania następuje natychmiastowe ponowne wejście do przerwania mimo że ramki juz nie ma. W tym wypadku wyjście jest takie że musisz mieć pewnośc że dana ramka juz się skończyła i nie spowoduje juz żadnych zmian na wejściu INT i musisz skasować flagę przerwania od INT przed samym wyjściem z ISR INT. Funkcja SIGNAL ci nie pomoże ponieważ flagi od przerwań i tak są ustawiane.
  • Poziom 13  
    Witam !

    Wydaje mi się, że chodzi tu o rozróżnienie przerwań zewnętrznych od wenętrznych inny skok przy przerwaniu wew. a inny przy zew. W programie obsługi trzeba poprostu sprawdzać skąd przychodzi przerwanie i odpowiednio skskać.
    Obsługa klawiatury z przerwania nie jest dobrym pomysłem.

    pozdrowienia T

    Dodano po 3 [minuty]:

    Witam !

    Wydaje mi się, że chodzi tu o rozróżnienie przerwań zewnętrznych od wenętrznych inny skok przy przerwaniu wew. a inny przy zew. W programie obsługi trzeba poprostu sprawdzać skąd przychodzi przerwanie i odpowiednio skskać.
    Obsługa klawiatury z przerwania nie jest dobrym pomysłem.

    pozdrowienia T