Wednesday, June 27, 2012

AVR Tutorial - 5. Timers and Counters





1.                  Timers and Counters
·         Timers and Counters are the one of the most commonly used complex peripheral in a microcontroller.
·         They are used for getting time periods, generating pulse signals and also for measuring time period of pulses.
·         There are two main TIMER/COUNTER in ATMEGA32 : TIMER0(8-Bit) and TIMER1(16-Bit)
·         Timer0 will roll over after 255 and Timer1 will rollover after 65,535. So be careful about this roll over when using Timers in a µC.
·         TCNT0 is the counter for TIMER0 ie. It is like a variable which counts with the oscillation of system clock and rolls over back to 0.
·         Similarly TCNT1 is the counter for TIMER1.

Timer0:
Using timer 1 includes setting the appropriate values in the Timer Counter Control Register mainly for setting the speed / frequency at which TCNT0 is counting.


Program:



#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>


void main()
{
                DDRB = 0b00000011;
                PORTB = 0b00000000;
               
                TCCR0 = (1<<CS02) | (0<<CS01) | (1<<CS00); //   8MHz / 1024 as prescaler
                TCNT0 = 0;           
                int ctr1 = 0;
                int sec_ctr = 0;

                                               
                while(1)
                {
                                if(TCNT0 == 200)
                                {
                                                PORTB = 0b00000000;
                                                TCNT0 = 0;
                                                ctr1++;
                                                if(ctr1 == 39)
                                                {
                                                                ctr1 = 0 ;
                                                                PORTB = 0b00000001;
                                                                sec_ctr++;
                                                                if(sec_ctr >= 60) //checking for elapsing of one minute
                                                                {
                                                                                PORTB |= 0b00000010;
                                                                                sec_ctr = 0;
                                                                                _delay_ms(10);
                                                                }
                                                }
                                }
                }}
·         An interrupt is also being generated when the overflow of Timer occurs.
·         We need to unmask the TIMER0 overflow interrupt in the TIMSK registers and should use suitable ISRs.


·         The previous example could be done with the help of interrupts as given below:

#include <avr/io.h>
#include <util/delay.h>
#include<avr/interrupt.h>

int ctr1 = 0;
int sec_ctr = 0;

void main()
{
     DDRB = 0b00000011;
     PORTB = 0b00000001;
     TCCR0 = (1<<CS02) | (0<<CS01) | (1<<CS00);
     TIMSK = 0x01; //Enabling TIM0 ovf interrupt
     TCNT0 = 55;
     sei();
     int ctr1 = 0;
     int sec_ctr = 0;
     OCR0 = 0;
     while1)
     {
           //Do nothing…
     }
}




ISR(TIMER0_OVF_vect)
{
     TCNT0 = 55;
     PORTB = 0b00000000;
     ctr1++;
     if(ctr1 == 39)
     {
           ctr1 = 0 ;
           PORTB = 0b00000001;
           sec_ctr++;
           if(sec_ctr >= 60) //checking for elapsing of one minute
           {
                PORTB |= 0b00000010;
                sec_ctr = 0;
                _delay_ms(10);
           }
     }


}

TIMER1:
·         Timer1 is a 16 bit counter and rolls over occur after 65535.
·         Here the Timer Counter Control Registers are TCCR1A and TCCR1B
·         We will be using here just TCCR1B for setting the prescaler bits.





Program:
Source: www.newbiehack.com
#include <avr/io.h>
int main(void)
{
DDRB = 0b01111111;
PORTB = 0b00000000;
DDRD = 0b01111111;
PORTD = 0b00000000;
TCCR1B |= 1<<CS10 | 1<<CS11;
int LEDNumber[2];
while(1)
{
if (TCNT1 > 2232)
{
TCNT1 = 0;
PORTB = 1<<LEDNumber[0];
LEDNumber[0] ++;
if (LEDNumber[0] > 6)
{
LEDNumber[0] = 0;
PORTD = 1<<LEDNumber[1];
LEDNumber[1] ++;
if (LEDNumber[1] > 6)
LEDNumber[1] = 0;
}
}
}
}
·         We could also do this thing using interrupts:
Source: www.newbiehack.com
#include <avr/io.h>
#include <avr/interrupt.h>

int main(void)
{
sei();

DDRB |= 1<<PINB0;

TCCR1B |= 1<<CS10 | 1<<CS11 | 1<<WGM12;
TIMSK |= 1<<OCIE1A;
OCR1A = 15624;

while(1)
{
}
}

ISR(TIMER1_COMPA_vect)
{
PORTB ^= 1<<PINB0;
}

No comments:

Post a Comment