Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[ATmega8][C] - Power Down- wybudza się tylko raz

Wykolejony 11 Sie 2013 17:37 1803 12
  • #1 11 Sie 2013 17:37
    Wykolejony
    Poziom 11  

    Bawię się trochę w programowanie i utknąłem w pewny momencie.
    Założenia programu:
    -Po włączeniu zasilania uC przechodzi w stan głębokiego uśpienia.
    -Wciśnięcie przycisku budzi uC, które wysyła zapytanie do zewnętrznego RTC o sekundy
    -Surowe sekundy w BCD są wyswietlane na czterech LEDach
    -po około 5 sekundach uC gasi LEDy i idzie spać

    Urządzenie po włączeniu przechodzi w Power Down, po naciśnięciu przycisku wyświetla coś na LEDach, po 5 sekundach gaśnie i klops... nie można wybudzić go drugi raz.

    Złożone na jakiejś płytce z wyprowadzonymi goldpinami, którą dostałem razem z USBasp, dodałem tylko kondensatory na zasilanie, ledy na pająku ze wspólną katodą, przycisk masa-INT1 oraz PCF8563 na pająku.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dodam tylko że w takiej formie wykonuje się instrukcja if, więc program na pewno nie zawiesza się w pętli. Po wywaleniu uśpienia wszystko działa.

    0 12
  • Pomocny post
    #2 12 Sie 2013 10:10
    dondu
    Moderator Mikrokontrolery Projektowanie

    Witaj.

    Na początek uporządkuj sprawy dot. trybu usypiania, ponieważ wykonujesz niepotrzebnie w pętli głównej część czynności w tym zakresie.

    Poza tym skoro już używasz nagłówka sleep.h, to używaj go w pełni, a nie osobno ustawiasz np.

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zobacz przykład funkcji main tutaj:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    zaczerpniętej stąd: http://mikrokontrolery.blogspot.com/2011/03/R...rwien-odbior-danych-przyklad-AVR-ATmega8.html

    Więcej o sleep.h: http://www.nongnu.org/avr-libc/user-manual/group__avr__sleep.html
    Zdefiniowane nazwy pozostałych trybów dla wybranego mikrokontrolera, znajdziesz w pliku nagłówkowym sleep.h

    Dodatkowa uwaga:
    Nie definiuj F_CPU w kodzie z tych powodów: http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html

    0
  • Pomocny post
    #3 12 Sie 2013 10:20
    kicajbas
    Poziom 25  

    Witam
    Definicja funkcji

    Kod: c
    Zaloguj się, aby zobaczyć kod

    - brakuje void
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Pozdr.

    .

    0
  • #4 12 Sie 2013 12:55
    Wykolejony
    Poziom 11  

    Dziękuję za odpowiedzi.
    Wyrzuciłem definicję F_CPU i zmodyfikowałem główną pętlę wedle podanego wzoru:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Efekt wciąż ten sam. Jeśli zmienie tryb uśpienia na IDLE działa jak należy.

    Cytat:
    Definicja funkcji
    Kod: c
    Zaloguj się, aby zobaczyć kod

    - brakuje void


    Kompilator sam wrzucał tam int i działało, ale dzięki, już poprawiłem.

    0
  • #6 14 Sie 2013 12:40
    Wykolejony
    Poziom 11  

    W tygodniu nie mam tyle czasu i zapału żeby zgłębiać temat, także program wciąż wygląda tak:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Cytat:
    Efekt wciąż ten sam. Jeśli zmienie tryb uśpienia na IDLE działa jak należy


    Jedyne co mi przychodziło do głowy to to że może POWER DOWN miesza coś w rejestrach dot. przerwań, ale nigdzie nie znalazłem żadnej takiej informacji. Próbowałem także dodawać ustawienia bitów przerwania po wywołaniu funkcji sleep_cpu, aby po przebudzeniu wszystko ustawił jeszcze raz, ale nic to nie dało.

    0
  • #7 14 Sie 2013 13:08
    dondu
    Moderator Mikrokontrolery Projektowanie

    Aby ustalić, czy POWER DOWN działa poprawnie dla testu usuń z funkcji przerwania komunikację przez TWI i wstaw zwykłą zmianę stanu diody LED nr 1 na przeciwny oraz delay dla wyeliminowania drgań styków. Na końcu funkcji ISR zgaś flagę przerwania INT ponieważ w czasie delay drgania mogły ją ustawić ponownie.

    W pętli głównej natomiast sleep_cpu() daj na końcu pętli poza warunkiem if(), a przed nim zmianę stanu drugiego leda na przeciwny oraz delay.

    W ten sposób ustalisz na 100% czy mikrokontroler wchodzi w tryb uśpienia POWER DOWN (dioda nr 2 nie będzie migać samoistnie) oraz czy się wybudza po naciśnięciu przycisku na INT1.

    0
  • #8 14 Sie 2013 14:28
    Wykolejony
    Poziom 11  

    Wygląda na to że coś zadziałało :D

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Dioda 2 się zapala i zostaje w tym stanie czyli uśpienie zadziałało. Każde wciśnięcie przycisku zmienia stan diody 1, oraz 2 czyli przerwanie działa. Teraz spróbuje obsługiwać TWI za pomocą jakiejś utworzonej flagi. Tak chyba najrozsądniej?

    -----------------------------------------------------------------------------------------------

    Niestety co bym nie robił to program się zacina. Mogę wstawiać w przerwanie i do głównej pętli różne cuda z ręcznym ustawianiem portów i działa, ale wystarczy że dodam obsługę TWI (czy w przerwaniu czy w wprost do głównej pętli) i się zawiesza. I w drugą stronę: jeśli dodam TWI a wywalę uśpienie, albo zmienię na IDLE, program działa. Nie potrafię dojść w którym miejscu dochodzi do konfliktu, i irytuję się bo zaczynam błądzić po omacku bez zrozumienia problemu...

    0
  • #9 15 Sie 2013 14:45
    pbuhne
    Poziom 14  

    Masz dołączone rezystory pull-up na linie TWI ?

    Wydaje mi się że Twój problem jest zaszyty gdzieś w pętlach while w funkcjach TWI. Spróbuj uzyć diod do sygnalizacji, w której pętli akurat znajduje się program np:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    I wtedy jeśli problem leży w TWI, to będziesz wiedział która pętla się wiesza - jeśli dioda nr 1 będzie się świeciła cały czas, to znaczy ze nastąpiło zapętlenie w while.

    Taka metoda sprawdziła się u mnie, gdy mi raz na kilka-kilkanaście godzin, TWI zawieszało cały układ, a że na domiar złego wrzuciłem obsługę w przerwanie INT0, to dopiero reset pomagał. Obecni obsługę TWI mam w pętli głównej, a INT tylko do wystawiania flagi oraz uruchomiłem timeout na watchdogu i układ śmiga.

    Pozdrawiam, Piotrek.

    0
  • #10 20 Sie 2013 13:47
    Wykolejony
    Poziom 11  

    Rezystory są, a program nie zawiesza się w TWI. Przy programie z postu#6 po komunikacji z RTC i przepisaniu wartości na port z ledami, program sprawdza jeszcze czy ten port jest różny od zera po czym wykonuje opóźnienie 5s, zeruje port i idzie spać. Gdyby się zaciął w TWI nie wykonałby już gaszenia ledów po opóźnieniu.

    0
  • Pomocny post
    #11 20 Sie 2013 21:00
    zumek
    Poziom 39  

    Wykolejony napisał:
    ...Jedyne co mi przychodziło do głowy to to że może POWER DOWN miesza coś w rejestrach dot. przerwań ...

    A widzisz, o rejestrach przerwań pamiętasz, a o rejestrach TWI zapomniałeś.

    0
  • Pomocny post
    #12 20 Sie 2013 23:13
    pbuhne
    Poziom 14  

    Może ten link pomoże Link

    0
  • #13 22 Sie 2013 11:31
    Wykolejony
    Poziom 11  

    Wielkie dzięki za link! Zeruję TWSTO i TWEN w TWCR przed wywołaniem funkcji TWI i jak ręką odjął :D
    Problem rozwiązany.

    0