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.

[C] Obsługa przerwania przy przepełnieniu oraz wyplenienie PWM

baser 27 Gru 2011 19:38 2196 6
  • #1 27 Gru 2011 19:38
    baser
    Poziom 13  

    Proszę o wyrozumiałość, od niedawna zainteresowałem sie uC i nie moge znalesc odpowiedzi na nurtujący mnie problem. Jak skonfigurować timer 8 bitowy w uC abym mógł:
    1) obsługiwać przerwanie przy przepełnieniu timera
    2) obsługiwać wypełnienie PWM

    Code:
    TCCR2=(1<<WGM20)|(1<<WGM21)|(1<<CS20)|(1<<CS21)|(1<<CS22)|(<<COM20)|( <<COM21);
    
    TIMSK |= (1<<TOIE0);
    OCR2=128;


    Procedura obsługi przerwania po przepełnienia timera:
    Cytat:
    ISR(TIMER0_OVF_vect) { }


    Jaka jest procedura do ustawienia stanu wysokiego na nóżce gdy stan licznika jest wyższy\niższy niż stan OCR2

    0 6
  • #5 29 Gru 2011 02:29
    baser
    Poziom 13  

    Code:


    //############ Procedura obsługi przerwania od przepełnienia timera ############ 
    ISR(TIMER0_OVF_vect)   

    n++;
    if(n>=1000)  // Kwarc 16000000Hz / Prescaler 64 / timer 8 bitów czyli 256 - poczatek liczenia od 6 czyli 250 =1000Hz czyli 1us
         {
         n=00;
         sek++;
         if(sek>=60)
               {
               sek=0;
               min++;
               if(min>=60)
                   {
                   min=0;
                   godz++;
                   if(godz>=24)
                       {
                       godz=0;
                       }
                   }
               }
         n=0;
         }           



    void main(void)
    {   
         //########### I/O ###########   
         DDRB  |= (1<<FAN)    //Ustawienie pinsterujacegoFAN jako wyjscie
         PORTB |= (0<<FAN)    //Ustawienie stanu niskiego na wyjściu sterującym FAN (STAN POCZATKOWY)
         
         //######## konfiguracja timera ############## 
         TCCR2=(1<<WGM20)|(1<<WGM21)|(0<<CS20)|(0<<CS21)|(1<<CS22)|(0<<COM20)|(1<<COM21); //8bit Fast PWM, Prescaler 64,
         TIMSK |= (1<<TOIE0); //Przerwanie overflow (przepełnienie timera)
         TCNT2 = 6; 
         OCR2=128;
         
         sei(); //Globalne uruchomienie przerwań
         
         //##############główna pętla programu ##############
          while(1);
                   {
                   
         
                   }
    }


    Czyli: za każdym razem gdy wartość OCR2 jest mniejsza od wartości TIMERA2 na wyjściu OC2 czyli PB3 pojawia się stan wysoki, a gdy TIMER2 przepełni się (256) uruchomiona zostaje procedura przepełnienia ISR(TIMER0_OVF_vect) ?





    Czy wartość OCR2 mogę zastąpić zmienną typu int zdeklarować ja na początku programu jako np 128, a następnie zmieniać tą zmienną w trakcie działania programu? Chodzi mi o możliwość regulowania wypełnienia w trakcie działania pętli while(1).

    Czy zrobić to programowo:
    Code:
    #include <avr io.h>    
    
    #include <avr interrupt.h>   

     
    #define FAN PB1

    int i=0;
    int n=0;
    int sek=0;
    int min=0;
    int godz=0;


    //############ Procedura obsługi przerwania od przepełnienia timera ############ 
    ISR(TIMER0_OVF_vect)   

    n++;
    if(n>=1000)  // Kwarc 16000000Hz / Prescaler 64 / licznik 8 bitów czyli 256 - poczatek liczenia od 6 czyli 250 =1000Hz czyli 1us
         {
         n=00;
         sek++;
         if(sek>=60)
               {
               sek=0;
               min++;
               if(min>=60)
                   {
                   min=0;
                   godz++;
                   if(godz>=24)
                       {
                       godz=0;
                       }
                   }
               }
         n=0;
         }
    i++;
    if(i<=WYP)
              PORTB |= (1<<FAN);
    if(i>WYP)
              PORTB &=~ (1<<FAN);
    if (i>=100)
              i=0;           
                                   



    void main(void)
    {   
         //########### I/O ###########   
         DDRB  |= (1<<FAN)    //Ustawienie pinsterujacegoFAN jako wyjscie
         PORTB |= (0<<FAN)    //Ustawienie stanu niskiego na wyjściu sterującym FAN (STAN POCZATKOWY)

         //######## konfiguracja timera ############## 
         TCCR2=(1<<WGM20)|(1<<WGM21)|(0<<CS20)|(0<<CS21)|(1<<CS22)|(0<<COM20)|(1<<COM21); //8bit Fast PWM, Prescaler 64,
         TIMSK |= (1<<TOIE0); //Przerwanie overflow (przepełnienie timera)
         TCNT2 = 6;  // Poczatkowa wartosc timera =6 a nie 0
         
         sei(); //Globalne uruchomienie przerwań
         
         //##############główna pętla programu ##############
          while(1);
                   {
                   
         
                   }
    }


    I wtedy zmieniać wartość wypełnienia (WYP) w programie pomiędzy wartościami 0 a 100?

    0
  • #6 29 Gru 2011 07:53
    dondu
    Moderator Mikrokontrolery Projektowanie

    baser napisał:
    Czyli: za każdym razem gdy wartość OCR2 jest mniejsza od wartości TIMERA2 na wyjściu OC2 czyli PB3 pojawia się stan wysoki, a gdy TIMER2 przepełni się (256) uruchomiona zostaje procedura przepełnienia ISR(TIMER0_OVF_vect) ?

    Tak, przy takim ustawieniu jak w pierwszym kodzie, ale masz w nim błąd polegający na tym, że używasz Timer2, a włączasz przerwania od przepełnienia Timer 0:

    Kod: c
    Zaloguj się, aby zobaczyć kod


    Podobnie z wektorem przerwań - używasz wektora z Timer0:

    Kod: c
    Zaloguj się, aby zobaczyć kod

    zamiast z Timer2: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html


    W jakim celu ustawiasz:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Wstawiając kod na forum używaj SYNTAX, a nie CODE.



    baser napisał:
    Czy wartość OCR2 mogę zastąpić zmienną typu int zdeklarować ja na początku programu jako np 128, a następnie zmieniać tą zmienną w trakcie działania programu? Chodzi mi o możliwość regulowania wypełnienia w trakcie działania pętli while(1).

    Zmienną możesz sobie ustawić, ale zmiana wypełnienia PWM nastąpi dopiero przy zmianie rejestru OCR2. Oczywiście do OCR2 możesz zapisać wartość ze zmiennej, a nie tylko ze stałej. Daje Ci to możliwość dowolnego operowania wypełnieniem sygnału PWM.

    Przypadku drugiego kodu nie rozpatruję, bo ten pierwszy załatwi Twoje potrzeby :)

    0
  • #7 29 Gru 2011 16:01
    baser
    Poziom 13  

    dondu napisał:

    Masz w nim błąd polegający na tym, że używasz Timer2, a włączasz przerwania od przepełnienia Timer 0:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zmieniłem na:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    dondu napisał:

    Podobnie z wektorem przerwań - używasz wektora z Timer0:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    Zmieniłem na:
    Kod: c
    Zaloguj się, aby zobaczyć kod


    dondu napisał:

    W jakim celu ustawiasz:
    Kod: c
    Zaloguj się, aby zobaczyć kod



    Kwarc 16MHz
    Prescaler 64
    Timer2 8 bitów= 256, zaczynam liczyć od 6 aby otrzymać 250 kroków
    Częstotliwość przepełnienia= Częstotliwość Kwarcu \ (Prescaler * Timer2)
    Częstotliwość przepełnienia= 16000000\ (64*250)= 16000000\16000= 1000Hz czyli otrzymam przepełnienie co 1us. Wiec zliczając w instrukcji przerwania do 1000 otrzymuję dokładnie 1s, co wykorzystam do zegarka.

    Czyli zmieniając np tak jak tutaj w pętli while(1), wartość a, a potem przypisując ją do rejestru OCR2 osiągnę zmienne wypełnienie PWM na nóżce PB3?
    Kod: c
    Zaloguj się, aby zobaczyć kod

    0