WebElektronika

Timer1 modul alkalmazása időzítőként az ATmega8-as mikrovezérlőnél

person access_time 2016.01.29.
Folytatjuk tovább az Atmel által gyártott AVR8-as család megismerését. Most a 16 bites Timer1 számláló használatát tekintjük át.


A 8 bites AVR-ek bemutatását a Timer1 modullal folytatjuk. Ennek a perifériának a blokkvázlatát látjuk az első ábrán. A Timer1 "bemenete" lehet a T1 (számláló funkció), vagy a belső órajel, amely egy előosztón keresztül érkezik a Control Logic egységbe (1. ábra).

kep
1. ábra   A Timer1 blokkvázlata
 

Alkalmazhatjuk ezt a modult tehát időzítőként, számlálóként, de akár PWM előállítására is, erre szolgál a "Waverom Generation" blokk.

Ez a modul működhet 8 bites, de akár 16 bites módban is, a számlálás értéke a TCNT1 regiszterben (16 bites) jelenik meg. Ez a regiszter két 8 bites regiszterből (TCNT1L, TCNT1H) áll.

Látjuk az első ábrán, hogy a Timer1 felprogramozásához két vezérlőregiszter szükséges, a TCCR1A és a TCCR1B. Ezeknek a segítségével tudjuk beállítani a Timer1 üzemmódját, de akár az órajel előosztójának az értékét is.

A TCCR1A regiszter "felépítését" látjuk a 2. ábrán. A kezdeti érték az Atmel AVR-eknél logikai 0, tehát, ha nem akarjuk, hogy az OC1A/OC1B lábon jelváltás (vagy 0, vagy 1) legyen akkor, ha az OCR1A és TCNT1 regiszterek értéke megegyezik, akkor nem kell értéket adnunk a COM1A1-nek és a COM1A0-nak, hiszen, ekkor az értékük nulla, tehát normál üzemmódban történik a számlálás (3. ábra).

kep
2. ábra   A TCCR1A regiszter
 

A harmadik ábrán látjuk a TCCR1A regiszter értékadásának egy részletét.

kep
3. ábra   TCCR1A regiszter tulajdonságai (részlet)
 

Szintén több lehetőségünk van a TCCR1B regiszter megfelelő írásával (4. ábra).

kep
4. ábra   A TCCR1B regiszter
 

Itt tudjuk megadni az előosztó értékét, de azt is, hogy időzítő, vagy számláló módot szeretnénk-e beállítani a Timer1-nél (5. ábra).

kep
5. ábra   Órajel előosztójának a beállítási lehetőségei
 

Nézzünk most meg néhány példát, programozzuk fel a tesztpanelünkön található ATmega8-as mikrovezérlőt.

 

1. példa

Az első példában a D portot beállítjuk kimenetre, majd ezt a 8 bites regisztert töröljük, az az, a kimeneten logikai nulla jelenik meg.
Ezután a TCCR1A regiszter tartalmát nullázzuk, hogy normál módban működjön a Timer1 időzítő, tehát a modulban található komparátorokat nem használjuk fel. Mivel a kezdeti érték a regiszterben logikai nulla (2. ábra), ezért akár ez az értékadás el is hagyható.

A TCCR1B regiszter értékeadásával állítjuk be az órajelosztó értékét. A példában a CS11 és a CS10 bitek logikai 1 állapotba kerülnek, tehát az osztási arány 64 (5. ábra).

#include <avr/io.h>

int main(void)
{
    DDRD = 0xFF;
    PORTD = 0x00;
    TCCR1A = 0;        // nem kötelező
    TCCR1B = (1 << CS11) | (1 << CS10);
    TCNT1 = 0;
    while(1)
    {
        if (TCNT1 >= 0x1234)
        {
            TCNT1 = 0;
            PORTD++;
        }
    }
}

 

A következő sorban a Timer1 modul értékét (TCNT1) lenullázzuk, tehát a TCNT1 regiszter értékét töröljük.

A while végtelen ciklusban egy feltételes szerkezet található, ahol azt vizsgájuk, hogy a számlálás értéke eléri-e már a 0x1234 értéket. Ha igen, akkor a TCNT1 regisztert töröljük, a számlálás újra indul, illetve a D porton lévő értéket eggyel növeljük.

 

2. példa

A következő példánk nagyon hasonlít az előzőre, de itt az órajelosztás beállítása makrókkal történik, illetve a TCCR1A értékadást elhagytuk, hiszen ez teljesen felesleges.

#include <avr/io.h>

#define CLKDIV1()        { TCCR1B |= 1 << CS10;}
#define CLKDIV8()        { TCCR1B |= 1 << CS11;}
#define CLKDIV64()        { TCCR1B |= (1 << CS10) | (1 << CS11);}
#define CLKDIV256()        { TCCR1B |= 1 << CS12;}
#define CLKDIV1024()    { TCCR1B |= (1 << CS10) | (1 << CS12);}

int main(void)
{
    DDRD = 0xFF;
    PORTD = 0x00;
    CLKDIV64();
    TCNT1 = 0;
    while(1)
    {
        if (TCNT1 >= 0x1234)
        {
            TCNT1 = 0;
            PORTD++;
        }
    }
}