Čítače / Timery

Seznámení s ovládání timerů, jejich nastavování a využití přerušení od timeru. Nutné pro jakoukoliv práci s periodicky se opakující událostí. 

Řešené příklady:
•    Vytvořte periodicky opakující signál o zadané frekvenci
•    Vizualizujte danou úlohu

Zadání :

Pomocí přerušení timeru (CompA,B,C) postupně rozsvěcujte LED 1-3 (cca 1s) . Při přetečení timeru (OVF)  všechny 3 LED zhasněte. Pro názornost také blikejte LED 8 (100ms) - řešeno přes delay v hlavni smyčce.

Nápověda :

Funkce timeru
Timer (čítač) je speciální registr v paměti mikrokontroléru, který mění svou hodnotu v pevně stanovených periodách, nebo (dle nastaveni) dle přivedeného signálu na piny mikrokontroléru.
Timer je důležitou součástí pro různé aplikace jako jsou například :
- Čítač impulsů - hodnota timeru se mění dle počtu impulsů přivedených na piny timeru
- Měření času - při měření se spustí timer a dle počtu přesně daných period (taktů) lze určit výsledný čas
- Generování PWM signálu - jedna se o přesně definovaný časový průběh
- Opakovat akce v přesných časových úsecích - díky přerušení od čítače lze v jednom cyklu vyvolat až čtyři nezávislé přerušení viz obr.

timer-top.png

Na obrázku je znázorněn průběh při využití všech přerušení. Hodnoty registru OCRxA až OCRxC lze kdykoli skokově měnit. v Případě kdy hodnota timeru je rovna hodnotě registru OCRxx, vyvolá se příslušné přerušení. Při naplnění timeru se vyvolá přerušení OVF (overflow - přetečení) a dojde k vynulování hodnoty timeru. Tento režim se nazývá normální (Normal top) . Existuje ještě režim CTC (Clear To Compare - vynulovat při shodě), kdy timer nepočítá do "plna", ale do hodnoty pomocného registru např ICRx - který lze libovolně měnit. Tímto způsobem je  možné přesně nastavit i periodu (cyklus) timeru.

Inicializace Timeru 1 :

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// OC1C output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: On
// Compare C Match Interrupt: On
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
OCR1CH=0x00;
OCR1CL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x1C;
ETIMSK=0x01;

Vektory přerušení timeru :
ISR(TIMER1_COMPA_vect)     
{
}

ISR(TIMER1_COMPB_vect)     
{
}

ISR(TIMER1_COMPC_vect)     
{
}

ISR(TIMER1_OVF_vect)     
{
}

Řešení :


#define F_CPU 16000000UL   
#include <avr/io.h>
#include <string.h>
#include <util/delay.h>
#include <avr/interrupt.h>

//*******************************************************************************************
//  MOJE UPRAVY
//-------------------------------------------------------------------------------------------
//
#define setb(port,pin)    port |= 1<<pin    //nastav bit
#define clrb(port,pin)    port &= ~(1<<pin) //nuluj bit
#define negb(port,pin)    port ^= 1<<pin    //neguj bit

//***********************************************************************************

volatile unsigned char compA=0;
volatile unsigned char compB=0;
volatile unsigned char compC=0;
volatile unsigned char plno=0;

ISR(TIMER1_COMPA_vect)     
{
compA=1;
}

ISR(TIMER1_COMPB_vect)     
{
compB=1;
}

ISR(TIMER1_COMPC_vect)     
{
compC=1;
}

ISR(TIMER1_OVF_vect)     
{
plno=1;
}


void main(void)
{

// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 15,625 kHz
// Mode: Normal top=FFFFh
// OC1A output: Discon.
// OC1B output: Discon.
// OC1C output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: On
// Input Capture Interrupt: Off
// Compare A Match Interrupt: On
// Compare B Match Interrupt: On
// Compare C Match Interrupt: On
TCCR1A=0x00;
TCCR1B=0x05;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1AH=0x00;
OCR1AL=0x00;
OCR1BH=0x00;
OCR1BL=0x00;
OCR1CH=0x00;
OCR1CL=0x00;

// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=0x1C;
ETIMSK=0x01;


DDRB=0xFF; // vystupní - Ledky
DDRD=0x00; // vstupní  - Tlacitka




// Global enable interrupts
sei();



// zablikani na zacatku
  PORTB=0;
  _delay_ms(500);
   PORTB=255;
  _delay_ms(500);
    PORTB=0;
  _delay_ms(100);
   PORTB=255;
  _delay_ms(100);


PORTB=255;

while (1)
      {


OCR1C=16000;
OCR1B=32000;
OCR1A=48000;


  negb(PORTB,7);
  _delay_ms(100);


if (compA==1)
        {
            negb(PORTB,0);
            compA=0;

        }

if (compB==1)
        {
            negb(PORTB,1);
            compB=0;

        }

if (compC==1)
        {
            negb(PORTB,2);
            compC=0;

        }

if (plno==1)
        {
            PORTB=255;
            plno=0;
        }

      };
}