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

[AVR] Power-down - problem z wybudzaniem procesora

ulumulu 06 Kwi 2012 21:07 2797 15
REKLAMA
  • #1 10765096
    ulumulu
    Poziom 10  
    Witam.
    Dopiero zaczynam programować uC AVR. Zaczynam od ATmega8L, ostatnio mam problem z przerwaniem zewnętrznym INT0, układ wchodzi w stan uśpienia ale nie można go wybudzić. W czasie normalnej pracy przerwanie działa i zmienia licznik. Ogólne prawidłowe działanie programu powinno być takie, że dioda zapala się 10 krotnie po czym uC wchodzi w stan uśpienia. Przerwaniem mamy wybudzić i przywrócić licznik. Poniżej przedstawiam mój kod, nie mogę doszukać się błędu. Prosiłbym po pomoc.
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #define F_CPU 1000000L
    #include <avr/sleep.h>
    
    volatile int8_t licznik = 20;
    
    void spij(){
    	MCUCR |= (1<<SE) | (1<<SM1);
    	sleep_mode();
    }
    ISR(INT0_vect){
       	MCUCR &= 0b00001111;
    	licznik=20;
    	
    }
    ISR(TIMER1_COMPA_vect){
    	if(licznik>0){
    		licznik--;
    		PORTC^=0x01;	
    	} else {
    		PORTC &= ~_BV(1);
    		spij();
    	}
    }
    ISR(BADISR_vect){}
    int main(void)
    {
    	DDRC=0xFF;
    	PORTC=0;
    	GICR = _BV(INT0);
    	MCUCR |= _BV(ISC01); 
    	DDRD &= ~_BV(PD2);
    	PORTD |= _BV(PD2);
    	DDRD |= _BV(PD6);
    	PORTD &= ~_BV(PD6);
    	PORTC |= _BV(2);
    	//ustawienia Timera1
    	OCR1AH = 0xF4;
    	OCR1AL = 0x24;
    	TCCR1A = 0;
    	TCCR1B |= _BV(CS11) | _BV(WGM12);
    	TIMSK |= _BV(OCIE1A);
    	sei(); 
        while(1)
        {
            //TODO:: Please write your application code 
        }
    }
    
  • REKLAMA
  • #2 10765402
    mirekk36
    Poziom 42  
    Musisz doczytać w nocie, że aby wybudzić procka trzeba to zrobić poziomem a nie zboczem, a ty jak ustawiasz ???

    MCUCR |= _BV(ISC01);

    widzisz o co chodzi ? (skasuj tą linijkę - to będzie wyzwalane stanem niskim i będzie OK)
  • REKLAMA
  • #3 10765424
    ulumulu
    Poziom 10  
    No próbowałem tak i tak i MCUCR |= _BV(ISC01); i MCUCR =0; Nic to nie dało. Już drugi dzień szukam błedu.
  • #4 10765462
    mirekk36
    Poziom 42  
    To nie jest kwestia żeby sobie próbować i tak i tak - na chybił trafił - może coś zadziała. Trzeba robić po kolei , świadomie i zgodnie z notą PDF.

    Pomijam że nawet nie napisałeś co ci nie działa ? tylko żeby szukać błędu.
  • REKLAMA
  • #5 10765515
    ulumulu
    Poziom 10  
    Napisałem przecież wcześniej że nie działa obsługa przerwania zewnętrznego. Dopóki uC nie wejdzie w stan uśpienia przerwanie działa i zmienia licznik. I znowu rozpoczyna od 20 aż dojdzie do 0 i sie usypia. Tyle że po tej czynności na przewanie nie reaguje, a powinien. I nie sprawdzam od tak sobie, raczej linijka po linijce. Korzystam też z książki i dokumentacji pdf.
  • #6 10765695
    mirekk36
    Poziom 42  
    Spróbuj licznik ustawiać na 20 tuż przed zaśnięciem a nie w przerwaniu INT.... tak na razie na sucho myślę..... Ale bezwzględnie nie ustawiaj przypadkiem wybudzania ZBOCZEM jak wcześniej tylko koniecznie poziomem NISKIM..... Aha no i sprawdź czy masz podciąganie tej linii do VCC - to MUSI działać w takiej konfiguracji.
  • REKLAMA
  • #7 10766125
    zumek
    Poziom 39  
    Nie usypiaj uC, jak masz wyłączone przerwania :!:
  • #8 10766203
    dondu
    Moderator na urlopie...
    Podsumujmy:

    1. Pull-up masz włączony prawidłowo,

    2. Przerwania globalne oraz przerwania z INT0, także prawidłowo.

    3. Proponuję, abyś zdecydował się, czy sam ustawiasz bity rejestrów odpowiedzialnych za usypianie, albo korzystał ze zdefiniowanych makr. Aktualnie w Twoim kodzie ustawiasz dwa razy flagę SE - raz samodzielnie, drugi raz w wykorzystując sleep_mode(). Dla uproszczenia sugeruję wykorzystanie zdefiniowanych makr tak:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    4. Sposób generowania przerwania masz ustawiony nieprawidłowo o czym pisał Mirek. Powinieneś mieć:

    [AVR] Power-down - problem z wybudzaniem procesora

    czyli, by wybudzić z POWER DOWN trzeba mieć ustawione wyzwalanie niskim, poziomem, a Ty masz na początku ustawiony:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    czyli:

    Cytat:
    Any logical change on INT1 generates an interrupt request.


    5. Ponieważ wykorzystujesz sleep_mode(), to ta operacja jest niepotrzebna:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    ponieważ definicja sleep_mode() zawiera:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    6. No i na koniec pytanie o to, jak generowane jest przerwanie na pinie INT0? Przycisk?

    PS.
    Wstawiając na forum kod używaj znacznika SYNTAX nie CODE. Miałeś odpowiedni komunikat na czerwonym tle, gdy wstawiałeś CODE.
  • #9 10766695
    ulumulu
    Poziom 10  
    Kod zmieniłem tak jak radziliście. MCUCR |= _BV(ISC01); usunąłem, wiec mam przerwanie stanem niskim. W funkcji spij() wpisałem ustawienia sleep_mode ale nadal to nie pomogło. Najciekawsze jest to ze w książce którą mam jest podobne zadanie i ono działa.
    Poniżej zadanie z książki.
    Przyciskiem na PD0 wprowadzam w Power-down, a INT0 budzę
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Tutaj jest moje zadanie z wprowadzonymi zmianami. Nadal działanie takie samo. Próbowałem też licznik przypisywać przed wywołaniem funkcji spij() żeby odciążyc INT0, też nic nie pomogło. Działanie prawidłowe z licznikiem jest tylko dopóki nie wejdzie w sleep.
    Poniżej kod:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod

    Załączam jeszcze poglądowy rysunek.
    [AVR] Power-down - problem z wybudzaniem procesora
  • #11 10767096
    mirekk36
    Poziom 42  
    A ja zapytam krótko - próbowałeś końcu wybudzać procesor z podawaniem normalnie GND na pin INT0 ???? a nie z tego pinu PD6 ??? - to chyba powinien być podstawowy dla ciebie test

    Tak jak masz też oczywiście da się zrobić - ale właśnie trzeba sobie najpierw dobrze założenia rozpisać i wtedy napisać pod to program. Ty na pewno nie masz jeszcze napisanego programu, który mógłby działać z takim schematem jak pokazałeś na tym rysunku.

    Sprawdź więc wybudzanie z podawaniem GND na INT0 i zobacz/napisz czy to ci działa.
  • #14 10767279
    ulumulu
    Poziom 10  
    mirekk36 napisał:

    Sprawdź więc wybudzanie z podawaniem GND na INT0 i zobacz/napisz czy to ci działa.


    Sprawdziłem i nic to nie daje. Jeżeli chodzi o rysunek to właśnie zadanie z ksiażki które wcześniej podałem na takim schemacie działa. Obsługa wejść jest raczej dobrze napisana. PD2 jest wejściem z podciagnięciem do 1, a PD6 wyjściem z podciagnieciem do 0. Nie wiem czego się tu jeszcze mogę złapać, logicznie to powinno działać.
    Ogólnie zadanie brzmi tak:
    Po dziesięciokrotnym mrugnięciu diody D1 w odstępach 0,5s układ ma przejść w tryb uśpienia. Jeśli wykryte zostanie przyciśnięcie przycisku S1, liczenie mrugnięć należy zacząć od początku. Także wyjście z tryby uśpienia ma nastąpić w wyniku wykrycia wciśnięcia przycisku S1.
  • #15 10767855
    dondu
    Moderator na urlopie...
    Zumek już podpowiedział co jest problemem.
    W momencie gdy wykonujesz funkcję spij() masz wyłączone przerwania, ponieważ jesteś w funkcji obsługi przerwania i dlatego nie możesz wybudzić mikrokontrolera. Możesz przed spij dać sei(). Ale ja proponowałbym jednak przeniesie spij(), na koniec pętli while() w main().
  • #16 10768021
    ulumulu
    Poziom 10  
    Ok. Już teraz rozumie. Dziekuje za pomoc.
REKLAMA