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.

m32, konfiguracja przerwania TIMER1

atek000 29 Gru 2011 17:23 1248 4
  • #1 29 Gru 2011 17:23
    atek000
    Poziom 17  

    Witam wszystkich. W końcu wziąłem się za naukę C, tym bardziej, że zakupiłem książkę naszego forumowicza mirka (polecam książkę, lekko napisana i ta po "chłopsku") oraz wpadł mi w ręce zestaw startowy z and-tech EvB 4.3
    (bardzo podobny do tego z ATNEL-a). Pierwsze kroki z diodą i wyświetlaczem LCD za mną. Przerwanie i migoczącą diodą także.

    Problem mam z konfiguracją przerwania TIMER1

    Code:

    #include <avr/io.h>
    #include <util/delay.h>
    #include <avr/interrupt.h>

    //----definicja segmentow----
    #define sA (1<<PC0)
    #define sB (1<<PC1)
    #define sC (1<<PC2)
    #define sD (1<<PC3)
    #define sE (1<<PC4)
    #define sF (1<<PC5)
    #define sG (1<<PC6)

    //----definicja cyfr------
    #define c0 ( sG)
    #define c1 ( sA | sD | sE | sF | sG)
    #define c2 ( sC | sF)
    #define c3 ( sE | sF)
    #define c4 ( sA | sD | sE)
    #define c5 ( sB | sE)
    #define c6 ( sB)
    #define c7 ( sD | sE | sF | sG)
    #define c8 (0)
    #define c9 ( sE)
    #define ce ( sB |sC)

    //----zmienne globalne----
    uint8_t zn,CAX;

    uint8_t *wsk;

    // --- *** Program Glowny *** ---
    int main(void)
    {
       DDRC |= (sA | sB | sC | sD | sE | sF | sG); //piny do lcd
       DDRA |= (1<<PA0);                     //pin do diody

    //--- konfiguracja przerwania ---
       TCCR1B |= (1<<WGM12);               //ustawienie TIMER1 w tryb CTC
       TCCR1B |= ((1<<CS12)|(1<<CS10));      //ustawienie prescalera
       OCR1A =15625;                     //wartosc w rejestrze do porownania
       TIMSK |= ((1<<OCIE1A) | (1<<OCIE1B));   //zezwolenie na przerwanie od timer1
       sei();

       CAX=1;                           //ot takie sobie przypisanie
    //--- petla---
       while(1)
       {
          zn=CAX;

          switch (zn)            //konwersja cyfry na konkretne segmenty
          {
             case 0:
                zn=c0;
                break;




             case 1:
                zn=c1;
                break;
             case 2:
                zn=c2;
                break;
             case 3:
                zn=c3;
                break;
             case 4:
                zn=c4;
                break;
             case 5:
                zn=c5;
                break;
             case 6:
                zn=c6;
                break;
             case 7:
                zn=c7;
                break;
             case 8:
                zn=c8;
                break;
             case 9:
                zn=c9;
                break;
             default:
                zn=ce;
          }
          PORTC=zn;               //wyslanie cyfry juz zamienionej
    portu C

          wsk=&CAX;
          ++*wsk;
          if (*wsk>=10) *wsk=0;
          PORTA ^=(1<<PA0);         //zmiana stanu diody
          _delay_ms(4000);

       }
    }

    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {

    }


    Wiem że kod jest nieco zagmatwany i niepotrzebne są wskaźniki i przerwanie ale właśnie się ich uczyłem i dlatego zastosowałem.
    W tym przypadku włączone jest przerwanie, ale jest puste. Wykonywać powinien się tylko główny program zliczający CAX, "przekonwertować" na odpowiednie segmenty, wysłać do portu c, zwiększyć CAX, zmienić stan dodatkowej diody na PA0, odczekać 4s i ... tyle, wraca i robi znów to samo. Międzyczasie wykonuje się puste przerwanie co 1s.
    Natomiast u mnie dioda miga co 1s a na LCD mam wciąż cyfrę 1, jaka był przypisana na początku jeszcze przed pętlą.

    Program działa prawidłowo jeżeli całą konfigurację przerwania oraz samo przerwanie ujmę w komentarz.
    Code:

    /*
    //--- konfiguracja przerwania ---
       TCCR1B |= (1<<WGM12);               //ustawienie TIMER1 w tryb CTC
       TCCR1B |= ((1<<CS12)|(1<<CS10));      //ustawienie prescalera
       OCR1A =15625;                     //wartosc w rejestrze do porownania
       TIMSK |= ((1<<OCIE1A) | (1<<OCIE1B));   //zezwolenie na przerwanie od timer1
       sei();
    */


    Code:

    /*
    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {

    }
    */


    Wówczas wyświetlana cyfra się zwiększa wraz ze zmianą stanu diody co 4s.

    0 4
  • Pomocny post
    #2 29 Gru 2011 17:31
    tadzik85
    Poziom 38  

    a co z przerwaniem porównania kanału B?

    0
  • #3 29 Gru 2011 18:18
    atek000
    Poziom 17  

    Faktycznie, nie mam pojęcia po co wpisywałem OCIE1B. Pozostawiłem

    Code:
       TIMSK |= (1<<OCIE1A);   //zezwolenie na przerwanie od timer1
    i jest teraz ok.
    Tą konfigurację robiłem jakiś czas temu i chyba myślałem że trzeba załączyć A i B.


    Teraz zmiana i dążenia właśnie do tego co zamierzałem i znów zong. Zliczanie miało odbywać się w przerwaniu. Wiem, że przerwanie to swego rodzaju funkcja a do funkcji z niej należy zmienne przekazywać. Ja właśnie chciałem użyć wskaźników.
    Code:
    #include <avr/io.h>
    
    #include <util/delay.h>
    #include <avr/interrupt.h>

    //----definicja segmentow----
    #define sA (1<<PC0)
    #define sB (1<<PC1)
    #define sC (1<<PC2)
    #define sD (1<<PC3)
    #define sE (1<<PC4)
    #define sF (1<<PC5)
    #define sG (1<<PC6)

    //----definicja cyfr------
    #define c0 ( sG)
    #define c1 ( sA | sD | sE | sF | sG)
    #define c2 ( sC | sF)
    #define c3 ( sE | sF)
    #define c4 ( sA | sD | sE)
    #define c5 ( sB | sE)
    #define c6 ( sB)
    #define c7 ( sD | sE | sF | sG)
    #define c8 (0)
    #define c9 ( sE)
    #define ce ( sB |sC)

    //----zmienne globalne----
    uint8_t zn,CAX;

    uint8_t *wsk;

    // --- *** Program Glowny *** ---
    int main(void)
    {
       DDRC |= (sA | sB | sC | sD | sE | sF | sG); //piny do lcd
       DDRA |= (1<<PA0);                     //pin do diody

    //--- konfiguracja przerwania ---
       TCCR1B |= (1<<WGM12);               //ustawienie TIMER1 w tryb CTC
       TCCR1B |= ((1<<CS12)|(1<<CS10));      //ustawienie prescalera
       OCR1A = 15625;                     //wartosc w rejestrze do porownania
       TIMSK |= (1<<OCIE1A);   //zezwolenie na przerwanie od timer1
       sei();

       CAX=1;                           //ot takie sobie przypisanie
    //--- petla ---
       while(1)
       {
          zn=CAX;

          switch (zn)            //konwersja cyfry na konkretne segmenty
          {
             case 0:
                zn=c0;
                break;
             case 1:
                zn=c1;
                break;
             case 2:
                zn=c2;
                break;
             case 3:
                zn=c3;
                break;
             case 4:
                zn=c4;
                break;
             case 5:
                zn=c5;
                break;
             case 6:
                zn=c6;
                break;
             case 7:
                zn=c7;
                break;
             case 8:
                zn=c8;
                break;
             case 9:
                zn=c9;
                break;
             default:
                zn=ce;
          }
          PORTC=zn;               //wyslanie cyfry juz zamienionej na port C
       }
    }

    //---przerwanie---
    ISR(TIMER1_COMPA_vect)
    {
            wsk=&CAX;
       ++*wsk;
            if (*wsk>=10) *wsk=0;
            PORTA ^=(1<<PA0);         //zmiana stanu diody
    }


    No i dioda miga a cyfra się nie zmienia.

    0
  • Pomocny post
    #4 29 Gru 2011 19:48
    tadzik85
    Poziom 38  

    słowo kluczowe "volatile"

    0
  • #5 29 Gru 2011 20:59
    atek000
    Poziom 17  

    Faktycznie, dziękuję i ponownie poleciał przycisk "pomógł". Źle zrozumiałem opis z książki str.79. Dzisiaj poprawiłem wiadomości z przerwania od TIMER1, zapoznałem się ze wskaźnikami i zmiennymi typu "volatile". Dzień był udany :D

    0