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

Bascom - Atmega 128 i zerowanie flagi przerwania zewnętrznego

czajnik01 09 Gru 2012 17:56 3501 10
REKLAMA
  • #1 11630437
    czajnik01
    Poziom 11  
    Witajcie

    Napotkałem następujący problem - Mam układ komunikujący się szeregowo z procesorem w sposób następujący:

    1. Układ wywołuje przerwanie
    2. Odbieram dane statusu od układu
    3. Wychodzę z przerwania

    i to działa.

    Problem zaczyna się jeżeli odebrane dane statusu wymuszają w procesorze kolejne operacje z użyciem układu. Ponieważ idzie to tak:

    1.Układ wywołuje przerwanie
    2.Odbieram dane statusowe w wywołanym przerwaniu
    3.Wysyłam do układu żądanie wykonania operacji
    4.Układ po wykonaniu operacji zgłasza przerwanie
    5.Wysyłam do układu żądanie wykonania operacji
    6.Układ po wykonaniu operacji zgłasza przerwanie
    itd.... aż do końca obsługi.

    I tu zaczyna się problem. Układ działa dość szybko więc powyższe punkty wykonuję w obsłudze pierwszego pojawiającego się przerwania (pkt.1) czekając programowo bitwait-em na wykonanie zadanej układowi przez procesor operacji (pkt.4 i 6). W efekcie po obsłudze całego cyklu komunikacji po kolejnych przerwaniach programowych ze tak je nazwętypu pkt.4 i 6 pozostaje ustawiona sprzętowa flaga przerwania zewnętrznego w procesorze czyli po wyjściu z obsługi przerwania procesor od razu ponownie w nie wchodzi.

    Wg. mojej teorii sprawę powinno załatwić zwykłe resetowanie rejestru flag ExternalInterruptsFlagRegister EIFR. Niesety nie działa to zupełnie. Próbowałem i prostego Reset EIFR jak i wstawek asm jednak nie chce mi to zadziałać. Flaga się nie zeruje - wiem to z tąd ze układ w kółko wchodzi w przerwanie jak i po resecie flagi napisałem funkcję if testującą tą flagę. Warunek ten za każdym razem wskazuje ze bit EIFR.0 (bo INT0 używam) jest ustawiony.

    Końcowo powtórzę że jeśli komunikuję się z układem w taki sposób ze nie korzystam z jego opcji zgłaszania końca zadanej pracy to wszytko działa super. problem zaczyna się jeśli w trakcie obsługi przerwania pojawi się kolejne żądanie przerwania (pkt.4 i 6) którego nie potrafię na ten moment wyzerować wychodząc z przerwania.

    Macie jakieś pomysły jak to ugryźć?
    Z góry dziękuję


    Dodano:

    Co ciekawe usiłowałem jeszcze programowo zamiast zerować to ustawiać flagę EIFR.0 tak aby wywołać przerwanie. Niestety bezskutecznie. Tak jakbym w ogóle nie miał programowego dostępu do rejestru EIFR.

    Przetestowałem też chyba wszystkie możliwe składnie...

    set INTF0

    set EIFR.0

    asm
    sbi $38,0
    end asm
  • REKLAMA
  • Pomocny post
    #2 11631335
    Konto nie istnieje
    Poziom 1  
  • REKLAMA
  • #3 11631396
    czajnik01
    Poziom 11  
    Wyzwalam zboczem.... i robię dokładnie tak jak mówisz... na samym końcu czyszczę wszystkie flagi od przerwań zewnętrznych. Nie zgodzę się że wpisując jedynkę bo katalog wyraźnie mówi ze jedynka wyzwala przerwanie ale to nie ma znaczenia bo sprawdzałem i tak i tak. Co ciekawe kod:

    reset eifr.0
    if eift.0 = 1 then set led

    Zapala leda. Czyli flaga nie zostaje wyzerowana :/ sprawdzałem też różnorakie wstawki asm jak i różen kombinacje kodu bascomowego. Trafiłem w straszny zułek i nie widzę wyjścia. :(

    Co gorsza mam prototyp na atmedze 8 który własnie w ten sposób (komendą reset GIFR ) działa bez problemu. Po napisaniu kodu na podstawie tego z atmegi8 na atmege 128 nie smiga.
  • Pomocny post
    #4 11631551
    Konto nie istnieje
    Poziom 1  
  • #5 11631966
    czajnik01
    Poziom 11  
    Więc po kolei...
    1.tak w tym kodzie jest błąd :) ale w programie go nie ma ponieważ nie kopiowałem tylko pisałem w poście od nowa.

    2.na moja wiedzę flaga jest zerowana w momencie skoku do przerwania a nie w momencie powrotu z niego.... w momencie skoku zerowana jest flaga wystąpienia przerwania i zerowana flaga globalnego zezwolenia przerwań. W momencie powrotu zerowana jest nie flaga konkretnego przerwania tylko ustawiana flaga zezwolenia przerwań wszystkich. Testowanie flagi w przerwaniu powinno wiec dać wynik zero lub jedynkę w przypadku jeśli w trakcie przerwania wystąpiło kolejne.

    Może się mylę?

    3.eicra utawiam składnią

    config int0 = falling

    więc jeśli nie używam innych przerwań zewnętrznych zapewne jest ustawiony na 0x02

    4.Dlaczego mam testować eimsk? skoro on po konfiguracji przy resecie procka się nie zmienia? chyba ze to literówka rejestrowa i tam miało byc eifr to tak testowałem... i robiłem to skłądnią:

    reset eifr.0 'zresetowanie bitu
    if eifr.0 = 1 then set led 'wyrzucenie na zewnątrz jesgo stanu

    ku mojemu przerazeniu mimo zresetowania wywalało jedynkę...
  • REKLAMA
  • Pomocny post
    #6 11632007
    Mundi1970
    Poziom 24  
    Żeby skasować flagę przerwania w rejestrze, musisz zapisać "1". Znajdziesz to w dokumentacji mikrokontrolera. Cytat z polskiego tłumaczenia:
    Flaga jest zerowana po wykonaniu procedury obsługi przerwania. Lub może zostać wyczyszczona poprzez wpisanie logicznej jedynki do niej.
  • REKLAMA
  • Pomocny post
    #7 11632054
    Konto nie istnieje
    Poziom 1  
  • #8 11632347
    czajnik01
    Poziom 11  
    Ok niech będzie ze jednyka natomiast ani z jedynką ani z zerem nie chce dziłać...

    Chciałem się dobrać do tego od innej strony to znaczy programowo wywołać przerwanie zapisując do eifr programowo zero czy jednykę. Poniżej znaczące wycinki kodu:

    Kod: text
    Zaloguj się, aby zobaczyć kod


    Wg mojego powinno sie wywołać przerwanie co około 200ms. Niestety ni hu hu nie chce ruszyć.

    Co do tłumaczeń to jednak w oryginale brzmi to tak:
    -When an edge or logic change on the INT7:0 pin triggers an interrupt request, INTF7:0 becomes set (one).

    Co dla mnie w wolnym tłumaczeniu brzmi
    -Kiedy zbocze lub poziom logiczny na pinie przeniwania 7-0 się zmieni wywoła to rządanie przerwania i przywoła w bitach INTF 7-0 ustawienie (jednykę)
  • Pomocny post
    #9 11632921
    Fredy
    Poziom 27  
    czajnik01 napisał:



    ldi R16,0
    Out &H38 , R16


    spróbuj to zamienić na :
    ldi R16,1
    Out &H58 , R16

    czajnik01 napisał:



    Co do tłumaczeń to jednak w oryginale brzmi to tak:
    -When an edge or logic change on the INT7:0 pin triggers an interrupt request, INTF7:0 becomes set (one).

    Co dla mnie w wolnym tłumaczeniu brzmi
    -Kiedy zbocze lub poziom logiczny na pinie przeniwania 7-0 się zmieni wywoła to rządanie przerwania i przywoła w bitach INTF 7-0 ustawienie (jednykę)


    ty piszesz o ustawianiu się flag a koledzy pisali o ich kasowaniu się. Nie widzisz różnicy?
  • #10 11633116
    czajnik01
    Poziom 11  
    No włąśnie tu tkwił mój błąd w rozumowaniu.... po północnym siedzeniu doszedłęm do takich wniosków.. tzn nie łączyłem tego ze żeby uzyskać zero trzeba zapisać jedynkę. Jednocześnie chciałem przez ustawianie flagi wywoływać przerwanie a to jest chyba niewykonalne wiec i tu straciłem trochę czasu.

    Kwitując:
    Uruchomiłem.... dziękuję za pomoc.

    Dla potomnych:

    1. Flaga przerwania ustawia sie w logiczną jedynkę w momencie przyjścia żądania przerwania
    2. Flaga jest zerowana w momencie skoku czyli rozpoczęcia obsługi przerwania
    3. Jeśli w trakcie przerwania przyjdzie kolejne przerwanie które jest dla nas niepożądane to aby je usunąć trzeba skasować flagę z jedynki logicznej na zero. Aby to zrobić należy zapisać jedynkę:

    If "flaga_przerwania" = 1 then set "flaga_przerwania"

    Słownie jeśli jest jedynka to zapisz kolejną jedynkę a otrzymasz zero.

    4. Jeśli flaga jest zero to zapisując jedynkę nie ustawimy flagi a tym samym nie da się programowo wywołać przerwania ze tak to nazwę "od środka". Można to wykonać tylko przez ustawienie zewnętrznej nóżki na którą ma przyjść obsługiwane zewnętrzne przerwanie.

    Jeszcze raz dziękuję za pomoc...

    Swoją drogą będę musiał dokładnie przejrzeć program pierwotny bo jeśli tam "wizualnie" działa polecenie RESET Gifr to znaczy ze działa to tylko na zasadzie jakiś hazardów które szczęśliwie się poskładały.
  • #11 11633301
    dondu
    Moderator na urlopie...
    czajnik01 napisał:
    No włąśnie tu tkwił mój błąd w rozumowaniu.... po północnym siedzeniu doszedłęm do takich wniosków.. tzn nie łączyłem tego ze żeby uzyskać zero trzeba zapisać jedynkę.

    To jedna z największych pułapek AVR-ów: http://mikrokontrolery.blogspot.com/2011/04/avr-czyhajace-pulapki.html


    Co do reszty czytajmy datasheety:

    Cytat:
    When an edge or logic change on the INT7:0 pin triggers an interrupt request, INTF7:0 becomes
    set (one). If the I-bit in SREG and the corresponding interrupt enable bit, INT7:0 in EIMSK, are
    set (one), the MCU will jump to the 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. These flags are
    always cleared when INT7:0 are configured as level interrupt. Note that when entering sleep
    mode with the INT3:0 interrupts disabled, the input buffers on these pins will be disabled. This
    may cause a logic change in internal signals which will set the INTF3:0 flags. See “Digital Input
    Enable and Sleep Modes” on page 69 for more information.

    by nie tracić czasu ...
REKLAMA