Vaša IP adresa: 18.216.123.120
Počet návštev: 30487

Lekcia 2: Časovač

Bude doplnený text.

Dôležité registre

V tejto časti sú opísané niektoré registre a ich bity súvisiace s nastavením časovača Timer0, ktoré sú využité v príkladoch nižšie.


TCCR0A - Register slúži hlavne na výber módu 8-bitového časovača Timer0.

reg_TCCR0A.png
  • Na výbere módu časovača sa uplatňujú bity WGM02, WGM01 a WGM00. Pozor bit WGM02 je obsiahnutý v registri TCCR0B! Nastavenie módu sa vykonáva podľa tabuľky nižšie. Bližšie opíšem iba mód 2, pretože tento mód sa často využíva a je použitý aj v príklade č. 4. Tento mód sa skrátene nazýva CTC (Clear Timer on Compare Match), čo znamená, že časovač "počíta" do hodnoty, ktorá je uložená v registri OCR0A. Po dosiahnutí tejto hodnoty dochádza k automatickému nulovaniu hodnoty časovača (register TCNT0) a pokračovaní v inkrementácii časovača.
reg_TCCR0A_table.png

TCCR0B - Register slúži hlavne na výber frekvencie 8-bitového časovača Timer0.

reg_TCCR0B.png
  • Bit WGM02 sa uplatňuje pri výbere módu časovača Timer0. Nastavenie módu je uvedené pri popise registra TCCR0A.
  • Na nastavenie frekvencie (periódy časovača) slúžia bity CS02, CS01 a CS00. Nastavenie frekvencie časovača sa odvíja od frekvencie MCU. V nasledujúcej tabuľke je uvedené nastavenie frekvencie časovača Timer0. V prípade, že niektorý z bitov CS02, CS01 alebo CS00 nie je nastavený na logickú nulu (okrem prvého riadka v tabuľke), dochádza k automatickému spusteniu časovača.
reg_TCCR0B_table.png

TCNT0 - Register (8-bit), ktorý uchováva aktuálnu hodnotu 8-bitového časovača Timer0. Register umožňuje čítanie aj zápis. Zápis do registra TCNT0 blokuje (odstráni) Compare Match pri nasledujúcom impulze časovača. Ak budeme modifikovať hodnotu TCNT0 pri spustenom časovači, tak sa môže stať, že nedôjde ku Compare Match medzi TCNT0 a OCR0A.

reg_TCNT0.png

OCR0A - Register (8-bit), ktorý obsahuje 8-bitovú hodnotu, ktorá je neustále porovnávaná s hodnotou časovača TCNT0. Zhoda registrov TCNT0 a OCR0A môže vyvolať prerušenie alebo generovať signál na vývode OC0A v závislosti od nastavenia módu časovača.

reg_OCR0A.png

TIMSK0 - Register (8-bit), ktorý slúži na vypnutie/zapnutie špecifického typu prerušenia v súvislosti s časovačom. Pre zapnutie/vypnutie špecifických prerušení slúžia registre OCIE0B, OCIE0A a TOIE0.

reg_TIMSK0.png
  • Ak je na bit OCIE0B zapísaná hodnota logickej jednotky a zároveň sú globálne povolené prerušenia (sei()), tak je zapnuté prerušenie Timer/Counter Compare Match B. Prerušenie je vyvolané nastavením bitu OCF0B v registri TIFR0.
  • Ak je na bit OCIE0A zapísaná hodnota logickej jednotky a zároveň sú globálne povolené prerušenia (sei()), tak je zapnuté prerušenie Timer/Counter Compare Match A. Prerušenie je vyvolané nastavením bitu OCF0A v registri TIFR0.
  • Ak je na bit TOIE0 zapísaná hodnota logickej jednotky a zároveň sú globálne povolené prerušenia (sei()), tak je zapnuté prerušenie pri pretečení časovača (timer overflow). Prerušenie je vyvolané nastavením bitu TOV0 v registri TIFR0.

TIFR0 - Register (8-bit), ktorý indikuje, či došlo k špecifickému typu prerušenia. Prerušenie je indikované pomocou bitov OCF0B, OCF0A a TOV0.

reg_TIFR0.png
  • Ak bit OCF0B obsahuje hodnotu logickej jednotky, tak došlo k zhode (Compare Match) medzi hodnotou časovača a hodnotou uloženou v registri OCR0B. Nulovanie bitu OCF0B je zabezpečené automaticky vykonaním zodpovedajúceho vektora prerušenia. Alternatívne môžeme bit OCF0B vynulovať manuálne zápisom logickej jednotky na tento bit. Ak je nastavený bit OCF0B a zároveň je nastavený bit OCIE0B tak dôjde k vykonaniu prerušenia (Timer/Counter Compare Match Interrupt).
  • Ak bit OCF0A obsahuje hodnotu logickej jednotky, tak došlo k zhode (Compare Match) medzi hodnotou časovača a hodnotou uloženou v registri OCR0A. Nulovanie bitu OCF0A je zabezpečené automaticky vykonaním zodpovedajúceho vektora prerušenia. Alternatívne môžeme bit OCF0A vynulovať manuálne zápisom logickej jednotky na tento bit. Ak je nastavený bit OCF0A a zároveň je nastavený bit OCIE0A tak dôjde k vykonaniu prerušenia (Timer/Counter Compare Match Interrupt).
  • Bit TOV0 sa zmení na jednotku keď dôjde k pretečeniu časovača. Nulovanie bitu TOV0 je zabezpečené automaticky vykonaním zodpovedajúceho vektora prerušenia. Alternatívne môžeme bit TOV0 vynulovať manuálne zápisom logickej jednotky na tento bit. Ak je nastavený bit TOV0 a zároveň je nastavený bit TOIE0 tak dôjde k vykonaniu prerušenia (Timer/Counter0 Overflow interrupt).

V nasledujúcich príkladoch sú uvedené rôzne spôsoby blikania LED s využitím časovača. LED má bliknúť 5x za sekundu, pričom čas rozsvietenej diódy je rovnaký ako čas zhasnutej diódy. Uvedenej situácii zodpovedá nasledujúci časový diagram.

casovac_led.png

Príklad č. 1

Bude doplnený text.

#include <avr/io.h>

int main(void)
{
DDRB=255; //PORTB ako vystupny (vsetky piny)
PORTB=0; //vsetky vystupy na log.0 -> vsetky LED zhasnute
TCCR0B|=(1<<CS01); // zapne casovac, predelicka 8 -> frekvencia casovaca 1 MHz
unsigned int pocet_preteceni=0; //pocitadlo preteceni
while (1)
{
if ((TIFR0&(1<<TOV0))==(1<<TOV0)) //ci nastalo pretecenie
{
pocet_preteceni++; //inkrementovanie poctu preteceni
TIFR0|=(1<<TOV0); //nulovanie priznaku pretecenia zapisom log.1
}
if (pocet_preteceni==391) //391 preteceni = 100.096 ms
{
pocet_preteceni=0; //aby sa odznova pocitali pretecenia
PORTB^=(1<<PORTB0); //zmena stavu LED na pine PORTB0
}
}
}

Príklad č. 2

Bude doplnený text.

#include <avr/io.h>

int main(void)
{
DDRB=255; //PORTB ako vystupny (vsetky piny)
PORTB=0; //vsetky vystupy na log.0 -> vsetky LED zhasnute
TCCR0B|=(1<<CS01); // zapne casovac, predelicka 8 -> frekvencia casovaca 1 MHz
unsigned int pocitadlo=0;
while (1)
{
if (TCNT0>=200) //ci ubehlo 200us
{
pocitadlo++; //inkrementacia pocitadla (kazdych 200us)
TCNT0=0; //nulovanie casovaca, aby znova pocital od nuly
}
if (pocitadlo==500) //ci ubehlo 100ms=500 x 200us
{
pocitadlo=0;
PORTB^=(1<<PORTB0); //bitova negacia
}
}
}

Príklad č. 3

Bude doplnený text.

#include <avr/io.h>

int main(void)
{
DDRB=255; //PORTB ako vystupny (vsetky piny)
PORTB=0; //vsetky vystupy na log.0 -> vsetky LED zhasnute
TCCR0B|=(1<<CS01); // zapne casovac, predelicka 8 -> frekvencia casovaca 1 MHz
OCR0A=200; //nastavenie registra zhody (200 = 200us)
unsigned int pocitadlo=0;
while (1)
{
//ci bit OCF0A v reg. TIFR0 je nastaveny na jednotku ->
//doslo k zhode TCNT0 a OCR0A
if ((TIFR0&(1<<OCF0A))==(1<<OCF0A))
{
pocitadlo++;
TIFR0|=(1<<OCF0A); //zmazanie priznaku zhody zapisom log.1
}
if (pocitadlo==500) //ubehlo 100ms=500x200us
{
pocitadlo=0;
PORTB^=(1<<PORTB0); //zmena stavu LED na pine PORTB0
}
}
}

Príklad č. 4

Bude doplnený text.

#include <avr/io.h>
#include <avr/interrupt.h> //kniznica preruseni

unsigned int pocitadlo=0;

ISR(TIMER0_COMPA_vect) //obsluha prerusenia casovaca0
{
//sem hlavny program (main) "odskoci" kazdych 200us
pocitadlo++;
if (pocitadlo==500) //ubehlo 100ms = 500 x 200us
{
pocitadlo=0;
PORTB^=(1<<PORTB0); //zmena stavu LED na pine PORTB0
}
}

int main(void)
{
DDRB=255; //PORTB ako vystupny (vsetky piny)
PORTB=0; //vsetky vystupy na log.0 -> vsetky LED zhasnute
TCCR0B|=(1<<CS01); // zapne casovac, predelicka 8 -> frekvencia casovaca 1 MHz
OCR0A=200; //nastavenie registra zhody (200 = 200us)

//automaticke nulovanie TCNT0 pri dosiahnuti hodnoty v OCR0A
TCCR0A|=(1<<WGM01);
TIMSK0=(1<<OCIE0A); //zapnutie prerusenia casovaca0
sei(); //globalne povolenie preruseni
while (1)
{
}
}