WebElektronika

Timer0 használata az AVR8-as családnál I.

person access_time 2015.12.03.
Az ATmega8-nál három időzítő/számláló található, ahol a Timer1 működhet 16 bites módban is. Most először a Timer0 (8 bites) modul alkalmazását nézzük meg néhány példa segítségével, de természetesen a Timer0-t (illetve a Timer1-et és a Timer2-t) a WebElektronikán futó sorozatunkban még részletesen fogjuk ismertetni.


Az ATmega8 mikrovezérlő Timer0 modulja látható az első ábrán. Ez a modul működhet időzítőként, ekkor a számlálandó periódikus jel az előosztóról érkezik. Illetve, használhatjuk 0->1 (vagy 1->0) átmenetek számlálására is, ekkor a jelünk a T0 (Tn) lábról érkezik. A számláló/időzítő aktuális értéke a TCNT0 (TCNTn) 8 bites regiszterben kerül eltárolásra.

kep
1. ábra   A Timer0 blokkvázlata
 

Ennek a modulnak a működése különböző lehet, ezért szükségünk van egy olyan regiszterre, amelynek segítségével a különböző üzemmódok beállításai eltárolhatók. Ez a regiszter a TCCR0 (TCCRn). Ennek a regiszternek a használatável tudjuk beállítani az előosztó méretét, amely az 1-estől (nincs előosztó), egészen az 1024-ig terjed (2. ábra).

kep
2. ábra   TCCR0 regiszter
 

1. példa

Készítsünk most egy programot, amellyel a Timer0 segítségével villogtatunk a D porton egy ledet. 

Először beállítjuk a D portot kimenetként (DDRD = 0xFF), majd a D port minden bitjét nullázzuk, tehát egyik LED sem fog világítani.
Ezután a TCCR0 regiszter írásával beállítjuk az osztási arányt (maximális értékre, az az 1024-re). Ennek végeztével a TCNT0 regisztert nullázzuk.

#include <avr/io.h>

void main()
{
    DDRD = 0xFF;
    PORTD = 0x00;
    TCCR0 = (1 << CS02) | (0 << CS01) | (1 << CS00);
    TCNT0 = 0;

    while(1)
    {
        if(TCNT0 == 200)
        {
            TCNT0 = 0;
            if (PIND & 0x04)
                PORTD = 0 << PD2;
            else
                PORTD = 1 << PD2;
        }
    }
}

 

A while(1) végtelen ciklusban állandóan figyeljük, hogy a TCNT0 értéke eléri-e a 200-at (érdemesebb lenne inkább használni a >= operátort). Amikor a TCNT0 értéke eléri a 200-at, akkor a TCNT0-t töröljük, majd megvizsgáljuk a PD2-es bit állapotát, majd ezt negáljuk.

Szebb megoldást kapunk, ha nem feltételes szerkezettel néznénk a PD2-es portbit állapotát, hanem készítenénk egy makrót, amely az állapotváltást valósítja meg. Ezt mutatja a következő példa.

#include <avr/io.h>
#define bitValt(cim,bit) (cim ^= (1 << bit))

void main()
{
    DDRD = 0xFF;
    PORTD = 0x00;
    TCCR0 = (1 << CS02) | (0 << CS01) | (1 << CS00);
    TCNT0 = 0;

    while(1)
    {
        if(TCNT0 == 200)
        {
            TCNT0 = 0;
            bitValt(PORTD,2);
        }
    }
}

 

A felhasznált makró már ismerős lehet egy korábbi cikkünkből.

 

2. példa

Valósítsunk meg most egy 8 bites számlálót, ahol a számláló értékét (TCNT0) megjelenítjük a D porton. A felhasznált C kód a következő :

#include <avr/io.h>

void main()
{
    DDRD = 0xFF;
    PORTD = 0x00;
    TCCR0 = (1 << CS02) | (0 << CS01) | (0 << CS00);
    TCNT0 = 0;

    while(1)
    {
        if(TCNT0 == 200)
        {
            TCNT0 = 0;
            PORTD++;
        }
    }
}

 

Az osztási arány 256, csak a CS02 bit van logikai 1-ben (2. ábra). Látható, hogy a while(1) végtelen ciklusban figyeljük a TCNT0 értékét, és ha eléri a 200-at, akkor nullázzuk a regiszter értékét, illetve a PORTD regiszter értékét eggyel növeljük.