Elektroda.pl
Elektroda.pl
X
Please add exception to AdBlock for elektroda.pl.
If you watch the ads, you support portal and users.

Atmega8 - Tym razem; przerwanie sprzętowe - nie działa

Michał 911 31 Mar 2013 21:20 3606 30
  • #1
    Michał 911
    Level 18  
    Witam,

    Od jakiegoś czasu próbuję włączyć przerwanie sprzętowe w uC ATmega8, robie wszystko zgodnie z datasheetem i nie działa :|

    Kto mi powie co tu jest nie tak? ;



    Code: c
    Log in, to see the code
  • #3
    KKK14
    Level 9  
    Jak zmienna używasz w przerwaniu i pętli głównej to musisz to zaznaczyć.
    "volatile int"
  • #4
    Michał 911
    Level 18  
    Ale nie tylko zmienna, a nawet samo ustawianie portu nie działa
  • Helpful post
    #5
    excray
    Level 40  
    SIGNAL(SIG_OVERFLOW0) - w ten sposób definiowały obsługę przerwania jeszcze nasze babcie i jeszcze za ich czasów wprowadzono nowy sposób - ISR(TIMER0_OVF_vect)
    3-sekundowy delay w przerwaniu? "Super" pomysł.
  • #6
    Michał 911
    Level 18  
    Quote:

    SIGNAL(SIG_OVERFLOW0) - w ten sposób definiowały wektor przerwania jeszcze nasze babcie i jeszcze za ich czasów wprowadzono nowy sposób - ISR...


    Aha, to sobie poszukam...

    Quote:

    3-sekundowy delay w przerwaniu? "Super" pomysł.


    To taka desperacka próba zauważenia czegokolwiek (testowo) - teoretycznie powinien się ten port na stałe ustawić, ale tak się zastanawiałem, czy przerwanie może w jakiś sposób go nie przestawia, więc na wszelki wypadek dałem delay'a
  • Helpful post
    #7
    Sparrowhawk
    Level 22  
    Wyrzuć te delay'e. Zmienną licznik jak radzili koledzy zmień na volatile. Zmień sei(); na SREG |= (1<<7);

    Jeśli będzie działać, to zapytam jakiej wersji avr studio używasz?

    Code: cpp
    Log in, to see the code
  • #8
    Michał 911
    Level 18  
    Działa!
    Przynajmniej tak ogólnie mogę to stwierdzić, bo sprawdzałem tylko tak na sztywno ustawianie jakiegoś portu w przerwaniu, jutro spróbuję z tym coś więcej zrobić.

    Quote:
    Jeśli będzie działać, to zapytam jakiej wersji avr studio używasz?


    Używam AtmelStudio 6.0
  • #9
    excray
    Level 40  
    Code: c
    Log in, to see the code

    Code: c
    Log in, to see the code

    Sparrowhawk wrote:
    Zmień sei(); na SREG |= (1<<7);
    To to samo więc jeśli została (a została) dołączona biblioteka interupt.h to nie ma różnicy.
  • #10
    Sparrowhawk
    Level 22  
    Zerowanie TCNT0 jest zbędne ale też niczemu nie przeszkadza. Co do makra sei(). Testowałem ten kod w debugerze AVR Studio 6 i w nim to makro nic nie robiło. Nie wiem, czy kolega Michał testował ten program w układzie, czy też w debugerze tylko. W każdym razie zauważ, że u niego makro sei() również nie działało. Wczoraj trudno mi było znaleźć informacje na ten temat, ale spotkałem się z opinią, że w najnowszym AVR Studio są z tym makrem problemy.
  • #11
    piotrva
    VIP Meritorious for electroda.pl
    Ogólnie powiem z całym szacunkiem, że z najnowszym AVR Studio jest sporo problemów.
    Dla początkujących do nauki polecam AVRStudio 4.18 - tam w zakresie podstawowych kostek serii Tiny AVR i Mega AVR wszystko działa poprawnie. (Jedynie najmniejsze kostki Tiny10/9/5/4 są w wersji 4.18 obsługiwane nieprawidłowo, serii XMega nie testowałem szczegółowo w tym IDE).
  • #12
    adam74m
    Level 12  
    A ja polecam Eclipse. Z sei() nie ma problemu. Poza tym działa i w Windows i Linux (u mnie na Ubuntu).
  • #13
    excray
    Level 40  
    adam74m wrote:
    A ja polecam Eclipse. Z sei() nie ma problemu. Poza tym działa i w Windows i Linux (u mnie na Ubuntu).

    Symulator/debugger też działa?
  • #14
    Michał 911
    Level 18  
    Kolej problem (myślę, że to też może być wina AS);

    pętla for(){} działa jak while(){}, czyli program wchodzi w for i nie wychodzi z niego dopóki warunek nie przestanie być spełniony

    Może po prostu coś źle robię, bo pierwszy raz używam przerwań sprzętowych.
    Pętla na której zatrzymuje się program wygląda tak;
    Code: c
    Log in, to see the code


    Aha i jeszcze jedno dziwne zachowanie for'a;
    jak mam takie coś (sekundnik dodaje się o 1 co każde przerwanie, zeruje jeśli jest większy od 36);
    Code: c
    Log in, to see the code


    dalej takie coś;
    Code: c
    Log in, to see the code


    i jeżeli w tych case'ach wpiszę że dioda ma się włączać jak sekundnik =1, a wyłączać jak jest = 7, potem znowu włączać jak jest = 22 i wyłączać jak jest 31, to włączy się tylko raz (między 22 a, 31)
    Czyżby ten for powyżej (od buzzera) coś robił z wartością sekundnik?



    Jeżeli z tego nic nie wynika, to tu na wszelki wypadek wstawiam cały kod;
    Code: c
    Log in, to see the code
  • #15
    BlueDraco
    MCUs specialist
    Pętla for w C działa tak, jak while. Zapis for (a; b; c) to to samo co:
    a;
    while (b)
    {
    ...
    c;
    }

    Zdefiniuj jako stałe preprocesora numery bitów LED i przycisków i używaj ich w kodzie - te maski bitowe nie są czytelne, a ich zmiana wymaga edycji wielu linii kodu.
  • #16
    Sparrowhawk
    Level 22  
    Co to za konstrukcja?
    Code: cpp
    Log in, to see the code


    Chyba powinno być:
    Code: cpp
    Log in, to see the code
  • #17
    excray
    Level 40  
    A ja dodam od siebie:
    Code: c
    Log in, to see the code
  • #18
    BlueDraco
    MCUs specialist
    Akurat nie, bo ++ jest w obsłudze przerwania. Dziwnawe rozwiązanie, ale jakoś tam działa.
  • #19
    Michał 911
    Level 18  
    To jeżeli for'em nie da się tego zrobić, to jak coś takiego zrobić, żeby to;
    Code: c
    Log in, to see the code

    wykonywało się przez określony czas (100 przerwań) i żeby nie zatrzymywało programu?
  • #20
    BlueDraco
    MCUs specialist
    To może po kolei:
    1. Co chcesz uzyskać i jak w związku z tym chcesz zaprogramować timery?
    2. Jaka jest częstotliwość procesora i czy ją poprawie zdefiniowałeś?
    3. Nie uruchamiaj timera przed jego zaprogramowaniem - robisz to obecnie z oboma timerami.
    4. Popraw tę bzdurę:
    licznik = 0;
    for(licznik==0;licznik<100;)
    5. Wyrzuć ze swojego kodu przełączanie trybów pracy - najpierw uruchom jeden z nich.
  • #21
    Michał 911
    Level 18  
    1. Układ wygląda tak;
    -jest 7 przełączników, 3 przyciski,
    -10 diod, które;
    *1-3, 5-7 mają po prostu gasnąć po przełączeniu hebla i na określony czas ustawiać PWM na konkretom wartość - przypisaną dla każdego przełącznika (tutaj PWM ma się ustawić tylko raz, a potem jak już dioda zgasła to ta linia ma być "nieczynna")
    *dioda 4 - od buzzera po przełączeniu hebla ma migać i co jakiś czas (co kilka przerwań) na jakiś czas ustawiać PWM na wartość przypisaną dla "tego przełącznika"
    *dioda 8 - stroboskopy, ta funkcja jest sterowana przyciskiem monostabilnym, ale w programie to zmieniłem, że działa jak bistabilny. Ta funkcja podobnie jak ta od buzzera ma co chwilę zmieniać wartość PWM (czyli np. jeżeli jest włączony buzzer i stroboskop to; ustaw PWM na 200, ustaw na 500, ustaw na 50-wartość domyślna i cały taki cykl trwa ok 1sek.), od buzzera różni ją jeszcze to, że mają być 2 mignięcia tej diody - przerwa, 2 mignięcia -przerwa ...
    *dioda 9,10 - światła - po wciśnięci przycisku monostabilnego diody mają się świecić cały czas, po ponownym wciśnięciu zostać wyłączone, kiedy są włączone PWM też musi się co chwilę zmieniać.

    Teraz właśnie tak to działa, ale jak przełączę przełącznik od diody 1-3, 5-7, to wtedy, program się na chwilę zatrzymuje - te diody co miały migać przestają migać, po upływie tego czasu (wyjściu z tej pętli for na której program się zatrzymuje) dalej wszystko działa normalnie

    2.
    Quote:
    2. Jaka jest częstotliwość procesora i czy ją poprawie zdefiniowałeś?

    O co chodzi z tym ponownym zdefiniowaniem?
    Procesor jest taktowany na 8MHz na wewnętrznym rezonatorze.

    3.
    Quote:
    3. Nie uruchamiaj timera przed jego zaprogramowaniem - robisz to obecnie z oboma timerami.

    Zaprogramowaniem, czy zdefiniowaniem?
    Czy o co chodzi?

    4.Pozmieniałem to we wszystkich for'ach, tylko nie w tym od buzzera, bo wtedy działa trochę inaczej (inaczej jak jest zmienione na sekundnik = 0; ); jak jest włączony stroboskop i włączę buzzer do dioda od stroboskopu przestaje migać (świeci się cały czas) i od buzzera też.

    5. To nawet nie wiedziałem, że mam to włączone. O który kawałek dokładnie chodzi?

    Tutaj wstawiam jeszcze raz trochę bardziej czytelny cały kod;
    Code: c
    Log in, to see the code


    Wszystko pięknie działa oprócz;
    *w tym switch'u na dole ten PWM nie ustawia się na 800, albo ustawia i od razu spowrotem przestawia na domyślną wartość 50.
    *tego opóźnienia powstałego na for'ach
  • #22
    dondu
    Moderator on vacation ...
    Koledzy wyżej po raz kolejny zwracają Ci uwagę, ale Ty nadal nie widzisz błędu, więc porównaj:
    - operator przypisania
    - operator relacji
    a na końcu zaglądnij do pętli for.


    Michał 911 wrote:
    4.Pozmieniałem to we wszystkich for'ach, tylko nie w tym od buzzera, bo wtedy działa trochę inaczej (inaczej jak jest zmienione na sekundnik = 0; ); jak jest włączony stroboskop i włączę buzzer do dioda od stroboskopu przestaje migać (świeci się cały czas) i od buzzera też.

    Jak ma działać konkretnie ten fragment?
  • #23
    Michał 911
    Level 18  
    Quote:
    Koledzy wyżej po raz kolejny zwracają Ci uwagę, ale Ty nadal nie widzisz błędu, więc porównaj:
    - operator przypisania
    - operator relacji

    Tzn., wiem jak działa przyrównanie i przypisanie, ale myślałem, że w pętli for może to być inaczej.

    Quote:

    Michał 911 napisał:
    4.Pozmieniałem to we wszystkich for'ach, tylko nie w tym od buzzera, bo wtedy działa trochę inaczej (inaczej jak jest zmienione na sekundnik = 0; ); jak jest włączony stroboskop i włączę buzzer do dioda od stroboskopu przestaje migać (świeci się cały czas) i od buzzera też.

    Jak ma działać konkretnie ten fragment?

    Otóż tak ma działać, że jak jest włączony buzzer (dioda miga) i stroboskop (2 mignięcia przerwa) i zostanie przełączony hebel np. od LED3, to wypełnienie PWM ma zostać zmienione na 300- LED3 gaśnie, tylko, że w międzyczasie jak ten PWM jest generowany (przez czas 100 przerwań) żeby diody od stroboskopu i buzzera nie przestawały migać, tylko migały swoim rytmem.

    Quote:
    a na końcu zaglądnij do pętli for.

    Chyba właśnie mnie oświeciło, zaraz zobaczę, czy będzie działać.
  • #24
    BlueDraco
    MCUs specialist
    W kodzie masz mnstwo bzdur. Przeanalizuj uwagi, które napisałem wcześniej. Są dość precyzyjne - po prostu czytaj i patrz w kod.
    W każdym obiegu pętli głównej ustawiasz OCR1A, ale oprócz tego w różnych instrukcjach warukowych zmieniasz tę wartość. Zmieniasz ją również wielokrotnie w tej nieszczęsnej pętli for - po co tyle razy?
    Ta pętla w ogóle jest dość bezsensowna, bo w kółko powtarzasz w niej to samo, a przecież w czasie jej wykonywania nie zmieni się ani stan diody, ani znacznika b.
    Sama struktura kodu jest taka, że wątpię, że to ma szansę działać zgodnie z założeniami, np. w kręcąc się w tej pętli for nic innego nie zrobisz.

    Nadmierne odstępy pionowe (puste linie) sprawiają, że kod trudniej się czyta.
  • #25
    Michał 911
    Level 18  
    Dobra, z diodami już sobie poradziłem, ale takie nijakie to moje rozwiązanie, bo po prostu zamiast tych pętli for dałem switch i diody działją, ale teraz PWM nie działa przestawia się co każde przejście pętli. Jeden z if'ów;
    Code: c
    Log in, to see the code


    Tylko jak to zrobić, żeby za każdym przejściem pętli ten PWM się nie zmieniał?

    Quote:
    W każdym obiegu pętli głównej ustawiasz OCR1A, ale oprócz tego w różnych instrukcjach warukowych zmieniasz tę wartość. Zmieniasz ją również wielokrotnie w tej nieszczęsnej pętli for - po co tyle razy?

    Aha, no faktycznie, czyli to ustawianie na wartość domyślną trzeba jakoś zmienić, np. że ustaw ją tylko, jeżeli, żadna funkcja nie jest włączona.

    Quote:
    Ta pętla w ogóle jest dość bezsensowna, bo w kółko powtarzasz w niej to samo, a przecież w czasie jej wykonywania nie zmieni się ani stan diody, ani znacznika b.


    No tak, dlatego zastąpiłem to case'em ale teraz PWM w ogóle się zepsuł bo w ciągu 1 przejścia pętli zmienia się kilka razy, czyli bardzo szybko.
  • #26
    BlueDraco
    MCUs specialist
    Pomyśl o zrobieniu wszystkeigo w przewaniu timera. Trudno coś dokładniej doradzić, bo Twoje opisy co do tego, co to ma robić, są strasznie mętne.
  • #27
    Michał 911
    Level 18  
    Już by mi wszystko działało tak jak chcę, ale przerwanie nie generuje się co 32ms (tak jak powinno), tzn. generuje się co taki czas, ale jeżeli nie jest w pętli for, jeżeli wejdzie w jakąś pętlę for, to najpierw musi z niej wyjść i dopiero potem się generuje, czy to normalne zachowanie przerwania?

    Teraz zmieniłem tylko końcówkę kodu od LED8 w dół (ale nawszelki wypadek stawiam cały);
    Code: c
    Log in, to see the code
  • #28
    stanleysts
    Level 27  
    Za dużo if-ów do czytania przełącznik zrób jako tablicę i pętla do tego.

    Przerwanie się wykonuje w zasadzie od razu (aktualna instrukcja się wykona a potem powinna iść obsługa przerwania) - tak mniej więcej bo to oczywiście zależy czy nie ma np. wywłaszczania przerwań, ale ogólnie żaden for ani inna pętla na to nie wpływa.

    Tak przy okazji to na jakiej podstawie stwierdzasz, że przerwanie generuje się później niż określony, założony czas?
  • #29
    BlueDraco
    MCUs specialist
    Znów pokazujesz kod, w którym jest mnóstwo błędów. Jeśli modyfikujesz ten sam port w przerwaniu i poza nim, to na czas modyfikacji w pętli (co jest tutaj zresztą zbędne, bo wszystko powinno chodzić w przerwaniu) musisz blokować przerwania.
  • Helpful post
    #30
    DawwidW
    Level 15  
    Weź uporządkuj ten kod, bo aż boli jak się to czyta :?