Professional Documents
Culture Documents
Basics
Timers come in handy when you want to set some time interval like your alarm. This can be very
precise to a few microseconds.
Timers/Counters are essential part of any modern MCU. Remember it is the same hardware unit
inside the MCU that is used either as Timers or Counter. Timers/counters are an independent unit
inside a micro-controller. They basically run independently of what task CPU is performing. Hence
they come in very handy, and are primarily used for the following:
Internal Timer: As an internal timer the unit, ticks on the oscillator frequency. The
oscillator frequency can be directly feed to the timer or it can be pre-scaled. In this mode
it used generate precise delays. Or as precise time counting machine.
External Counter: In this mode the unit is used to count events on a specific external pin
on a MCU.
Pulse width Modulation(PWM) Generator: PWM is used in speed control of motors and
various other applications.
Timer 0 Basics
Timer 0 is a 8 bit timer. It basically means it can count from 0 to 2^8 255. The operation of timer
0 is straight forward. The TCNT0 register hold the timer Count and it is incremented on ever y
timer "tick". If the timer is turned on it ticks from 0 to 255 and overflows. If it does so, a Timer
OverFlow Flag(TOV) is set.
You can as well load a count value in TCNT0 and start the timer from a specific count. Another
interesting feature is that a value can be set in the Output Compare Register (OCR0), and whenever
TCNT0 reaches that value, the Output Compare Flag (OCF0) flag is Set.
Timer/Counter 0
The configuration of the Timer can be set using the TCCR0 register shown below. With this you
can basically select two things:
1. The Frequency of the Clock Source with CS02, CS01, CS00 bits.
2. The mode of the timer. For the first example we will use it in normal mode where it ticks
from zero to the highest value (255)
Timer Counter Control Register 0
The Timer/counter Interrupt Flag Register (TIFR) holds the two basic flags we need the TOV and
OVF. Other bits correspond to the timer interrupts, which we will look at in another tutorial.
Timer/Counter 0 Flag Register
Example Code:
#include<avr/io.h>
#define LED PD4
int main()
{
uint8_t timerOverflowCount=0;
DDRD=0xff; //configure PORTD as output
TCNT0=0x00;
TCCR0 = (1<<CS00) | (1<<CS02);
while(1)
{
while ((TIFR & 0x01) == 0);
TCNT0 = 0x00;
TIFR=0x01; //clear timer1 overflow flag
timerOverflowCount++;
if (timerOverflowCount>=6)
{
PORTD ^= (0x01 << LED);
timerOverflowCount=0;
}
}
}
Timer 1 Basics
The Timer 1 is 16 bit, that means it can count from 0 to $$2^{16} = 65536$$. Hence the
Timer/Counter 1 is a 16 bit registered formed out of TCNT1H and TCNT1L as shown below.
Timer/Counter 1
Timer 3 also has 2 control registers which allow us to configure it and use it in any mode you wish.
Timer Counter Control Register 1A
Yes, and indeed we have a Flag register which will tell us the status of Timer 1 as shown below.
Timer/Counter 1 Flag Register
Example code:
#include<avr/io.h>
#include <util/delay.h>
#define LED PD4
int main()
{
DDRD |= (1<<LED) ; //configure led as outpout
TCCR1B = (1<<CS10) | (1<<CS12); //set the pre-scalar as 1024
OCR1A = 1562; //100ms delay
TCNT1 = 0;
while(1)
{
//If flag is set toggle the led
while((TIFR & (1<<OCF1A)) == 0);// wait till the timer overflow flag is SET
PORTD ^= (1<< LED);
TCNT1 = 0;
TIFR |= (1<<OCF1A) ; //clear timer1 overflow flag
}
}
Timer 2
Well, timer 2 is pretty similar to the timers covered above. Give it a shot, should you've any
questions do comment below.
Timers are independent units from the CPU. Hence if we use timers with Interrupts, it can make
the CPU free from polling the flags every-time. This is the way they are used normally
Modes of Operation
Asynchronous Normal Mode
In this mode of communication, the data is transmitted and received bit by bit without clock pulses
by the predefined baud rate set by the UBBR register.
Asynchronous Double Speed Mode
In this mode of communication, the data transferred at double the baud rate is set by the UBBR
register and set U2X bits in the UCSRA register. This is a high-speed mode for synchronous
communication for transmitting and receiving the data quickly. This system is used where accurate
baud rate settings and system clock are required.
Synchronous Mode
In this system, transmitting and receiving the data with respect to clock pulse is set UMSEL=1 in
the UCSRC register.
USART Configuration In AVR microcontroller
USART can be configured using five registers such as three control registers, one data register and
baud-rate-selection register, such as UDR, UCSRA, UCSRB, UCSRC and UBRR.
Before we go ahead with the examples here, are a few situations where you may want to use these:
Let's say you have a device like GSM interfaced to your Micro-controller using UART or
other serial interface. You simple do not know when you'll receive a new text message or
a call. One way to handle this is continuously monitor for the even to occur. The other way
is to configure a serial interrupt. Yes, you guessed it right, this is a Software Interrupt
indeed.
Now let's say you're building a music player. The main task of the processor is to read and
play back the audio file. However the player should be able to play/pause/forward/rewind.
And this could happen any time. How about connecting the switches to hardware interrupt
pins? The processor will be notified any time the events happen.
Steps to configure the Interrupts:
Set INT1 and INT0 bits in the General Interrupt Control Register (GICR)
Configure MCU Control Register (MCUCR) to select interrupt type.
Set Global Interrupt(I-bit) Enable bit in the AVR Status Register(SREG)
Handle the interrupt in the Interrupt Service Routine code.
Interrupt Sources
With AVR Micro-controllers, you can configure interrupts on various sources such as:
Port Pins : INT0, INT1 and INT2
Timers
UART
SPI
ADC
EEPROM
Analog Comparator
TWI or I2C
The vector table below shows the mapping of various interrupts. Notice that the RESET interrupt
has an address of $000, the first address of the program memory indeed.
Also notice that the next interrupt starts at an offset of 2 words(AVR Memory is word addressable
1 Word = 2 Bytes). Indeed no program can be stored in 4 bytes. What it will hold is a Jump
instruction to actual Interrupt service routine(ISR) in the memory. ISR, the name might sound
fancy, but it is nothing more than a program that executes once the interrupt is generated.
Interrupt Priority
Now you might wonder, what is I configure various interrupts and two or more interrupts happen
at the same time, which will get executed? The answer is it depends on the interrupt priority. For
AVR architecture it is simple. The lower the vector address, the higher the priority. Have a look
again RESET has the highest priority as might expect and other units later.
Example code:
#include<avr/io.h>
#include<avr/interrupt.h>
#include<util/delay.h>
#include "lcd.h"
volatile int cnt_zero,cnt_one;
ISR (INT0_vect) //External interrupt_zero ISR
{
cnt_zero++;
}
ISR (INT1_vect) //External interrupt_one ISR
{
cnt_one++;
}
int main()
{
DDRC=0xff; //Configure PORTC(Lcd databus) as output
DDRD=0xe0; //Configure INT0,INT1 as input and PORTD5-
PORTD7(rs,rw,en) as output
LCD_SetUp(PB_0,PB_1,PB_2,P_NC,P_NC,P_NC,P_NC,PB_4,PB_5,PB_6,PB_7)
;
LCD_Init(2,16);
while(1)
{
LCD_Printf("EINT0:%4u\n",cnt_zero);
LCD_Printf("EINT1:%4u\n",cnt_one);
}
}