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][C]Sterownie diodami LED w przerwaniu

Dawid237 20 Lis 2011 13:04 1798 21
REKLAMA
  • #1 10160331
    Dawid237
    Poziom 10  
    Witam poniższy kod to moje pierwsze podejście zaprogramowania uC z obsługa przerwań, oczywiście zakończone niepowodzeniem. Nie mam już pomysłu wiec proszę o pomoc, zaznaczam że nigdy nie miałem styczności z programowaniem, nauczyłem się jedynie operacji na bitach i kilku innych prostych rzeczy ale na przerwaniach się zatrzymałem. Chciałem uzyskać jakieś dwa proste efekty na LED-ach, wywołane najlepiej jednym przyciskiem. Próbowałem ale tak mi to wyszło:


    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h> 
    
    #define LED_FAST PORTB; 
                             
    #define LED_SLOW PORTB;
    
    #define LED_ON (1<<PD2);
    
    
    
    int main(void)
    
    {
    
        DDRB = 0xFF; //PORTY B JAKO WYJSCIA//
    	PORTB =0xFF; // WYGASZENIE LED
    	
    	DDRD |= ~(1<<PD2);  
        PORTD |= (1<<PD2);
    
       {
        LED_FAST;
    	_delay_ms(200);
    	PORTB = 0x18;
    	_delay_ms(200);
    	PORTB = 0x81;
    	_delay_ms(200);
    
    	LED_SLOW;
    	_delay_ms(500);
    	PORTB = 0x2F;
    	_delay_ms(500);
    	PORTB = 0xF2;
    	_delay_ms(500);
        }
    
        MCUCR |= (1<<ISC01)|(1<<ISC11); 
        GIMSK |= (1<<INT0);
    	sei();   
    
          while(1)  { }
    }
    
    SIGNAL (SIG_INTERRUPT0) 
    
    {
          DDRD |= ~(1<<PD2);  
          PORTD |= (1<<PD2);
    
    while(1)
    {
      if(!(LED_ON & 0x20)) PORTB = LED_SLOW;  
      else
      if                   PORTB = LED_FAST;
    }
    }
    
  • REKLAMA
  • #3 10161110
    McMonster
    Poziom 32  
    Ja zacznę od polecenia jakiegoś kursu C, bo kod jest miejscami taki sobie. W dalszej kolejności brakuje opisu, co w ogóle chciałeś osiągnąć, a co się rzeczywiście dzieje. Potem przydałby się schemat układu. Na koniec polecam przeczytanie tego artykułu i wyszukanie w spisie treści kursu C i artykułu o przerwaniach.
  • #4 10161970
    Dawid237
    Poziom 10  
    Dzieki za linki:) Szczerze na prostych podanych przykładach wiem jak to działa, jaka jest istota przerwań im więcej czytam tym bardziej się zastanawiam czy mój efekt LED mogę zrobić na przerwaniach, otóż ja chce uzyskać dwa efekty LED(na PORTB) i to w pętli "while(1)" i użyc "delay"(a tego się nie robi przerwaniach) maja się cały czas powtarzać, i to jedno przyciśniecie switcha włącza jeden efekt a drugie wyłącza pierwszy efekt a włącza drugi, i nie wiem za nic jak to zrealizować dlatego proszę o sugestie a ja będę dalej kombinował bo tylko tak się czegoś nauczę ale sam nie dojdę do tego proszę o podpowiedzi, nie widziałem niczego podobnego w sieci aby przeanalizować to i w końcu dowiedzieć się jak mam taki efekt uzyskać w C
  • #5 10162013
    D12
    Poziom 14  
    Cytat:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Ale ja tu nie widzę żadnej możliwości wyjścia z przerwania. Program utknie w pętli while w przerwaniu i nigdy z niego nie wyjdzie.

    To równie dobrze taki kod można zrobić w pętli głównej z tym, że przerwania będzie można jakieś dodać i będą one działać.
  • REKLAMA
  • #6 10162181
    Dawid237
    Poziom 10  
    A tak wyglądał pierwszy program który działał z tym ze kiedy trzymałem przycisk, no wtedy były dwa ale kwestia tego ze musiałem je trzymać, dlatego chce to zrobić jak pisałem wyżej:

    #include <avr/io.h>
    #include <util/delay.h>
    
    int main(void)
    {
    
    DDRB = 0xFF;
    PORTB = 0xFF;
    DDRD = 0x1F;
    PORTD = 0xFF;
    
    
    
    
    while(1)
    {
    if(!(PIND & 0x40))
    
    PORTB = 0x3C;
    PORTD = 0xFF;
    _delay_ms(1000);
    PORTB = 0xC3;
    _delay_ms(1000);
    
    
    if(!(PIND & 0x20))
    
    PORTD = 0x1F;
    PORTB = 0xFF;
    _delay_ms(1000);
    PORTD = 0x10;
    _delay_ms(1000);
    
    }
    
    }
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #8 10162316
    Dawid237
    Poziom 10  
    Tak ale to nic nie zmieni bo ja muszę trzymać jeden bądź drugi przycisk aby wykonało te polecenia.


    int main(void)
    {   
    
       DDRB = 0xFF;
       PORTB = 0xFF;
       DDRD = 0x1F;
       PORTD = 0xFF;
    
       while(1)
       {
         if(!(PIND & 0x40))
         {
          PORTB = 0x3C;
          PORTD = 0xFF;   
          _delay_ms(1000);
          PORTB = 0xC3;
          _delay_ms(1000);
         }
       
         if(!(PIND & 0x20))
        {
          PORTD = 0x1F;
          PORTB = 0xFF;
          _delay_ms(1000);
          PORTD = 0x10;
          _delay_ms(1000);
         }
       }
    }
  • REKLAMA
  • #9 10162347
    D12
    Poziom 14  
    Dawid237 napisał:
    if(!(PIND & 0x40))

    Dawid237 napisał:
    if(!(PIND & 0x20))


    Ty to chciałeś pewnie zrobić tak :)
    if(!(PIND & 0x04))
    if(!(PIND & 0x02))
  • #10 10162384
    snnaap
    Poziom 25  
    Hey rozumiem że masz dwa tryby: SLOW i FAST? I przyciskiem obsługiwanym w przerwaniu chcesz zmieniać te tryby?
    To proste jak budowa cepa;)

    Robisz tak w while { } masz dwie procedury:

    jedna z nich to:

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


    druga to:

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


    Załóżmy, że to która sekwencja będzie się wyświetlać będzie zależało od jakiejś tam zmiennej "sekwencja" czyli twoje całe while będzie wyglądało tak:

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



    W przerwaniu natomiast zmieniamy numer sekwencji, czyli:

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



    Aby troszkę ulepszyć dodajmy jeszcze najprostszą eliminację drgań, czyli przerwanie będzie wyglądało tak:



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


    i teraz złóż to w całość i powiedz czy osiągnęliśmy pożądany efekt jak tak to przejdziemy dalej.

    A w dalszym ciągu pokażemy prawidłową obsługę przerwania od przycisku, czyli nie wyrzucimy eliminacje drgań z przerwania.

    Dodano po 5 [minuty]:

    PS Brak jest ustawień dotyczących przerwania. Gdzie masz podpięty przycisk? Do INT0, INT1?
    Brak jest ogólnego włączenia przerwań. Jaki to uK?
  • #11 10162440
    Dawid237
    Poziom 10  
    A to nic nie zmienia, nie pomogło
  • #12 10162455
    snnaap
    Poziom 25  
    Nic nie pomogło bo jest brak ustawień przerwań, odpowiedz na pytania:

    "Brak jest ustawień dotyczących przerwania. Gdzie masz podpięty przycisk? Do INT0, INT1?
    Brak jest ogólnego włączenia przerwań. Jaki to uK? " i na pewno coś pomożemy

    Dodano po 1 [minuty]:

    PS można wywnioskować że to int0 jest?

    Dodano po 41 [sekundy]:

    Guzik pod PD2, Atmega8??
  • #13 10162490
    D12
    Poziom 14  
    No właśnie wróżenie z fusów. Jak przerobisz ten pierwszy kurs co ci wysłałem to ci gwarantuje, że to się czegoś nauczysz o przerwaniach.
  • REKLAMA
  • #14 10162498
    snnaap
    Poziom 25  
    A sorki nie przyuważyłem w pierwszym poście tego:

    MCUCR |= (1<<ISC01)|(1<<ISC11);
    GIMSK |= (1<<INT0);
    sei();

    i teraz wszystko jasne jest.

    Dodano po 9 [minuty]:

    Taki szybki gotowiec, sprawdź:
    Kod: C / C++
    Zaloguj się, aby zobaczyć kod


    Proszę nie krzyczeć, może kolega uczy się na przykładach.

    Przycisk podpięty pod PD2, LEDY na porcie B.

    Dodano po 1 [minuty]:

    Mała poprawka w kodzie była.

    Dodano po 2 [minuty]:

    Tak powinna wyglądać obsługa "prawidłowa" przerwania:

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #15 10162620
    Dawid237
    Poziom 10  
    Hej mam ATiny2313 podepnę pod INT0 jak ma działać na przerwaniach wcześniej miałem podpięte przyciski pod PD6,7
  • #17 10162826
    dondu
    Moderator na urlopie...
    snnaap napisał:
    Tak powinna wyglądać obsługa "prawidłowa" przerwania:

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


    Tak to wygląda NAJGORSZA z możliwych wersji obsługi przerwania:
    1. nie dość że stary rodzaj obsługi za pomocą SIGNAL() zamiast ISR(),
    2. to jeszcze oczekiwanie w przerwaniu,
    3. a na koniec cli() oraz sei() w przerwaniu.

    Kolego snnaap - nie ucz początkujących najgorszych z możliwych zasad programowania mikrokontrolerów.

    Dla autora tematu, by wiedział dlaczego nie powinien stosować opóźnień w przerwaniach: http://mikrokontrolery.blogspot.com/2011/04/problemy-c-przerwania.html

    oraz link do wektorów przerwań ISR(): http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
  • #18 10162844
    Dawid237
    Poziom 10  
    Wszystko ładnie się kompiluje, dodałem jeszcze kod ustawilem PD2 jako wejście oraz wygasiłem ledy na początek programu, ale nie działa podłączyłem oczywiście switch pod "minus"

    Kod: C / C++
    Zaloguj się, aby zobaczyć kod
  • #20 10162924
    dondu
    Moderator na urlopie...
    snnaap napisał:
    Dodu czytaj co piszemy od samej góry, a później wypowiadaj się w temacie.

    Nie ma usprawiedliwienia na takie propozycje jak proponujesz, które są absolutnie niezgodne ze sztuką programowania mikrokontrolerów. Tym bardziej nie ma na to zgody, gdy wpuszczasz na tak grząski teren osobę początkującą, która nabierze złych nawyków już na początku swojej drogi.
  • #22 10163004
    Dawid237
    Poziom 10  
    Hmm spokojnie chłopaki :) zobaczę jeszcze inny sposób na napisanie przerwania tez chce spróbować jak z tym kodem to by działało tylko coś mi nie działa kompiluje się bez warningow i tak jak zawsze programator nie zawodzi, nie wiem co nie tak, zaznaczę jeszcze ze mam wszystkie piny oprócz PD2 zajęte diodami ale to chyba nie ma znaczenia.
REKLAMA