Elektroda.pl
Elektroda.pl
X

Search our partners

Find the latest content on electronic components. Datasheets.com
Elektroda.pl
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega16 i przerwanie INT0 a deklaracje funkcji

20rafalo 10 Jul 2012 19:05 2153 29
  • #1
    20rafalo
    Level 19  
    Witam
    Mam problem z przerwaniem INT0.
    Mianowicie. Funkcję obsługi przerwania umieszczam przed "main", gdyż inaczej kompilator się nie kompiluje.
    Gdy funkcja obsługi przerwania jest pusta wszystko jest ok- tj ustawienie wszystkich bitów w rejestrach.
    Jeśli do funkcji obsługi przerwania "wrzucę" inne funkcje to wszystko się psuje.
    Dostaję błędy w postaci niezadeklarowanych funkcji, a one są w innych plikach. Do przerwania, które jest w pliku "main" również muszę dodawać "extern"? a co ze zmiennymi, które są zadeklarowane w main i s ą używane w przerwanu??

    Z góry dzięki..
  • #2
    gaskoin
    Level 38  
    Zamiast tak obrazowego opisu mógłbyś wrzucić kod? Z tego co napisałeś próbujesz w przerwaniu odwołać się do zmiennych lokalnych funkcji main, ale póki nie zobaczę kodu nic więcej powiedzieć nie mogę.
  • #3
    20rafalo
    Level 19  
    Code: c
    Log in, to see the code

    Reszta funkcji jest w innych plikach- myślę, że nie są potrzebne do wglądu.
    Dodam, że identyczna część kodu, która występuje w procedurze przerwania jest w funkcji "main" i działa bez zarzutu.
    Przerwanie ma po prostu zadziałać po przyciśnięciu przycisku i wyświetlić temperatury z innych urządzeń...

    Kompilatory nie generują błędów po małej poprawie kodu - dałem kilka zmiennych jako globalne.
    Jednak program nie działa fizycznie...

    Panowie już działa - dzięki ;)
    Jednak miałem dodatkowy problem układ czasami sam wchodził w przerwanie- bez wciskania przycisku...
    - musiałem dać rezystor podłączony do INT oraz do VCC- czyżby panował stan HI-Z??
  • #4
    gaskoin
    Level 38  
    20rafalo wrote:

    Panowie już działa - dzięki ;)
    Jednak miałem dodatkowy problem układ czasami sam wchodził w przerwanie- bez wciskania przycisku...
    - musiałem dać rezystor podłączony do INT oraz do VCC- czyżby panował stan HI-Z??



    Code: c
    Log in, to see the code


    Według tego kodu piny 0-3 są podciągnięte do vcc a piny 4-7 są w HiZ. Przyczyną takiego zachowania może być zła filtracja zakłóceń, ale póki nie ma schematu można w ciemno strzelać. Dodanie rezystorów deczko zwiększa odporność na cuda z linii zasilania więc szedł bym w tę stronę.

    Zmienne, które używasz w przerwaniu i w kodzie głównym trzeba zadeklarować jako volatile, ponieważ kompilator nie wie, że przerwanie zmienia stan zmiennej i optymalizuje trochę kod główny co często powoduje dziwne błędy. volatile nie zawsze jest konieczne, ale na początek przyjmij że trzeba je dawać zawsze gdy używasz zmiennej w przerwaniu i w mainie.

    Po przejrzeniu jeszcze kodu z grubsza mogę napisać jeszcze tylko, że wstawianie _delay_ms w przerwaniu (choć moim zdaniem i gdziekolwiek indziej) to barbarzyństwo. Blokujesz kod główny na grubo ponad 3 sekundy.
  • #5
    20rafalo
    Level 19  
    gaskoin wrote:
    Zmienne, które używasz w przerwaniu i w kodzie głównym trzeba zadeklarować jako volatile

    Właśnie się nad tym zastanawiałem, ale myślę, że nie trzeba, bo w przerwaniu INT funkcje ponownie pobierają wartości z innych czujników...
    Ale pewności nie mam....
    PS. Chodzi Ci o wszystkie zmienne globalne?? A co z funkcjami też tak deklarować?
    gaskoin wrote:
    Według tego kodu piny 0-3 są podciągnięte do vcc a piny 4-7 są w HiZ

    Tak, ale to nie ma znaczenia, bo przerwanie jest w porcie PD2- i jeśli ma przychodzić z zewnątrz to chyba nie trzeba delkarować tego pinu jako wejscie czy wyjście...
    Bo przecież to przerwanie może reagować na "1"; "0" itp...
    Fakt, że zawsze jest wejściem, ale bez deklaracji i tak działa. Chyba samo przerwanie to wymusza.. hmm...
  • #6
    gaskoin
    Level 38  
    20rafalo wrote:
    Właśnie się nad tym zastanawiałem, ale myślę, że nie trzeba, bo w przerwaniu INT funkcje ponownie pobierają wartości z innych czujników...


    Przecież napisałem, że kompilator o tym nie wie...

    20rafalo wrote:
    PD2- i jeśli ma przychodzić z zewnątrz to chyba nie trzeba delkarować tego pinu jako wejscie czy wyjście...
    Bo przecież to przerwanie może reagować na "1"; "0" itp...
    Fakt, że zawsze jest wejściem, ale bez deklaracji i tak działa. Chyba samo przerwanie to wymusza.. hmm...


    Przerwanie nic nie wymusza, tylko rejestry mają domyślne wartości na 0 (te akurat). Więc masz wejście w stanie HiZ, skoro nie skonfigurowałeś portu D. Może być wyjściem, ale zwierając je do masy możesz uszkodzić procesor (trzeba dać rezystor w szeregu). Czasami się tak robi, żeby programowo wywołać przerwanie.
  • #10
    gaskoin
    Level 38  
    Nie widzę powodów dla których kompilator miałby protestować. Zadziałał poprawnie bo masz tam przecież rezystor do vcc.
  • #11
    miszcz310
    Level 20  
    A ja tak chciałem wrzucić swoje 3 grosze. Funkcja _delay_ms() w przerwaniu, no proszę i to jeszcze 750 ms. Przecież to jest straszne, żeby procka blokować na 750 ms (dwa razy pod rząd) i to jeszcze w przerwaniu.
    Polecam zrobienie prostej maszyny stanów i użycie timera do przechodzenia pomiędzy stanami. Bo nawet jakbyś chciał dorobić jakąś obsługę klawiszy to przecież program będzie głuchy przez te 1,5 sek, albo możesz przecież wysłać komendę konwersji do wszystkich termometrów na raz i tylko raz czekać te 750ms.
  • #12
    20rafalo
    Level 19  
    miszcz310 wrote:
    Przecież to jest straszne, żeby procka blokować na 750 ms (dwa razy pod rząd) i to jeszcze w przerwaniu.

    Bo wyczytałeś, że _delay_ms nie powinno się tam stosować? Dla mnie ważne jest osiągnięcie zamierzonego celu.
    ...i nie jest w ogóle straszne, bo układ nie posiada dodatkowych funkcji, które by na tym traciły.
    A mi właśnie o to chodziło, aby przerwanie wystąpiło mimo opóźnień...
    Jeśli bym kiedyś dodawał funkcje to będę modyfikował..
    Są jeszcze priorytety przerwań - można by je wykorzystać...

    Pzdr
  • #13
    gaskoin
    Level 38  
    Nie chodzi o czytanie tylko o zdrowy rozsądek. Nawet w aplikacjach na PC nie blokuje się eventów na 3 sekundy... Skoro przerwanie jest Twoim kodem głównym to coś tu działa od tyłka strony :)
  • #14
    dondu
    Moderator on vacation ...
    20rafalo wrote:
    Bo wyczytałeś, że _delay_ms nie powinno się tam stosować? Dla mnie ważne jest osiągnięcie zamierzonego celu.
    ...i nie jest w ogóle straszne, bo układ nie posiada dodatkowych funkcji, które by na tym traciły.
    A mi właśnie o to chodziło, aby przerwanie wystąpiło mimo opóźnień...
    Jeśli bym kiedyś dodawał funkcje to będę modyfikował..

    Oczywiście kompromis jest dobry dopóki spełnia Twoje wymagania, a z tego co piszesz spełnia.
    Czy mógłbyś jednak zdradzić, co to za urządzenie, bo być może warto to zrobić inaczej?

    Z drugiej strony, nawet w takich projektach warto tak pisać programy jak sugerują koledzy wyżej, by wyrabiać właściwe przyzwyczajenie i umiejętności.
  • #15
    LordBlick
    VIP Meritorious for electroda.pl
    20rafalo wrote:
    Są jeszcze priorytety przerwań - można by je wykorzystać...
    1. INT0 ma najwyższy, więc nie wiem, jak to chcesz wykorzystać...
    2. Zrobisz naked, to ci coś wlezie w odliczanie takiej g...ej pauzy i potem padnie na tym forum sakramentalne "dlaczego mi to czasem nie działa ?" :P Timer w µC jest po to go używać.
  • #16
    20rafalo
    Level 19  
    dondu wrote:
    bo być może warto to zrobić inaczej?


    Są to 4 czujniki mierzące temperaturę wraz z małym intro podczas włączenia.
    Problem jest taki, że wyświetlacz pozwoli na wyświetlenie 2 wartości. Przerwanie powoduje nagłe włączenie kolejnych dwóch wartości. A opóźnienia są m.in dlatego, że potrzebne są czasu dla wyświetlacza, czujników i odczytania
    LordBlick wrote:
    Timer w µC jest po to go używać.


    Jeśli masz pomysł jak pozbyć się opóźnień, które spełniają w/w potrzeby to jestem zainteresowany ;P
    Pzdr
  • #17
    LordBlick
    VIP Meritorious for electroda.pl
    20rafalo wrote:
    Jeśli masz pomysł jak pozbyć się opóźnień, które spełniają w/w potrzeby to jestem zainteresowany
    Pomysł to był dawno:
    http://lmgtfy.com/?q=programowanie+zoptymaliz...d+wzgl%C4%99dem+wykorzystania+czasu+procesora
    Mam zrealizowane pod AVRasm2, przykład chociażby tutaj:
    https://www.elektroda.pl/rtvforum/topic1885957.html
  • #20
    miszcz310
    Level 20  
    Łoł się kolega zniecierpliwił...
    Piszę nie dlatego, że gdzieś to przeczytałem tylko wiem z własnego doświadczenia, że takich rzeczy lepiej unikać. W ogóle stosowanie funkcji generujących długie opóźnienia (tysiące cykli zegarowych) nie jest dobrym pomysłem, bo przez ten czas nie ma się żadnej kontroli nad układem.
    Co do rozwiązania to zaproponowałem maszynę stanów. Robisz coś takiego, żeby mieć przerwanie od timera co jakieś 100 ms. Masz zmienną globalną, którą inkrementujesz w każdym przerwaniu. Jak przejdzie przez 8 inkrementacji to minęło 800ms i robisz odczyt i zerujesz zmienną. dodatkowo polecam zrobić jeszcze tak, że w przerwaniu masz tylko warunki sprawdzające i wypełnianie tablicy z odczytanymi wartościami (ale bez żadnej konwersji). Jak odczytasz nowe wartości to ustawiasz flagę i w pętli głównej wywołuje sięfunkcją przeliczająca wartości z termometrów na "ludzki" format i wyświetlenie sprintfem. Ogólnie chodzi o to, żeby obsługa przerwania była możliwie jak najkrótsza.
  • #21
    20rafalo
    Level 19  
    LordBlick wrote:
    a resztę trzeba dopasować...

    Dopasowałem, działa ;)

    miszcz310 wrote:
    Co do rozwiązania to zaproponowałem maszynę stanów.

    Myślę, że ciekawy i sensowny sposób, muszę się zastanowić nad poprawą przerwania.
    Czyli przerwanie będzie 100ms, a nie 1500ms..
    Wnioskuję, że będzie dużo poprawek...
  • #22
    User removed account
    Level 1  
  • #23
    miszcz310
    Level 20  
    No widzę, że kolega voytaschec fajnie to opisał. Ja to mniej więcej też tak robię, a na pewno też tak dzielę kod na przerwania i main.
    Co do czasu wykonywania przerwania to nie będzie trwało 100ms. Tylko dużo, dużo, krócej bo tylko musi się wykonać przypisanie jednej zmiennej + wejście i wyjście z obsługi przerwania. Zatem przerwanie będzie trwało pewnie kilkanaście cykli, czyli jakieś powiedzmy pojedyncze mikro sekundy. Tylko jak chcesz mieć odpalanie z przycisku to w obsłudze tego przerwania od przycisku startujesz timer a jak się zrobi odliczenie całego cyklu to stopujesz timer i będziesz miał ładne rozwiązanie programowe. :P
  • #24
    User removed account
    Level 1  
  • #25
    stanleysts
    Level 27  
    Taki cooparative scheduling z warstwą przerwań jak to koledzy opisali wystarcza do większości zastosowań, jak już się aplikacja komplikuje a mamy w miarę procesor to tylko RTOS i jeszcze lepiej wszystko działa, tylko, że tam to już jest większa szkoła jazdy.
  • #26
    20rafalo
    Level 19  
    voytaschec wrote:
    To jest takie ogólne podejście, dzięki któremu można zrealizować większość projektów.

    Dzięki za fatygę ;)
    Jest to nowa lektura dla mnie ;P
    voytaschec wrote:
    w której umieszczam flagi

    Z nimi się jeszcze nie bawiłem. Mógłbyś podać jakiś ciekawy kurs, które przybliżają temat flag?
    Z góry dzięki.
  • #27
    McMonster
    Level 32  
    20rafalo wrote:
    voytaschec wrote:
    w której umieszczam flagi

    Z nimi się jeszcze nie bawiłem. Mógłbyś podać jakiś ciekawy kurs, które przybliżają temat flag?
    Z góry dzięki.


    Zmienne (np. boolowskie) określające wystąpienie danego zdarzenia. W przerwaniu ustawiasz taką zmienną, w głównej pętli programu po kolei sprawdzasz wszystkie flagi, jeśli dana flaga jest ustawiona, to wykonuje się odpowiedni dla niej kod. Umożliwia to skrócenie procedur obsługi przerwań do absolutnego minimum oraz sprawi, że wszystkie będą realizowane w przewidywalny sposób.
  • #28
    LordBlick
    VIP Meritorious for electroda.pl
    Ja tam skracam temat flag w ten sposób, że w przerwaniu Timera jakaś wartość jest odliczana do zera i dalej nie ruszana. Dopiero jakaś procedura w pętli głównej sprawdza czy jest zero, ustawia dalej odmierzanie czasu i podejmuje akcję.
  • #30
    gaskoin
    Level 38  
    Już ruszył, wystarczy poczytać na blogu