Timers and counter are the most used peripherals in a microcontroller. They are being able to measure time periods, measure frequency, determine pulse width or provide output signals. Example applications might include producing tones to create music, create a time base for a real time clock or measure rpm of an engine. Timers and counter are simply binary up-counters. In timing mode the binary counter are counting the time periods and in counter mode, they are counting the events or pulses.

 The AVR microcontrollers have both 8-bit and 16-bit timer/counters. An important issue for the program is to know when the counter reaches its maximum count and rolls over. The 8 bits counter rolls over from 255 to 0 and the 16 bits counter rolls over from 65.535. When a counter rolls over an interrupt is generated. 

TIMER/COUNTER PRESCALERS AND INPUT SELECTORS

Timer/counter units may use a variety of internal frequencies derived from the system clock as their input, or they may get their input from an external pin. The timer counter control register (TCCRx) associated with the timer contains the counter select bits (CSx2, CSx1, CSx0) that control which input is used with a specific counter. The figure below shows the prescaler and input selector configuration for a timer counter control register as used in most AVR microcontrollers.

The following code example shows how to initialize Timer 0 to use the system clock divided by 8 as its clock source (the counter select bits are the three least significant bits of TCCR0):

TCCR0 = 0x2; /* Timer 0 uses clock/8 */

TIMER 0

Timer 0 is a 8 bit timer/counter, it is most often used as a time base or a tick for the program. Timer counter control register 0 (TCCR0), controls the function of Timer 0 by selecting the clock source applied to Timer 0. A program tick, like the tick of a clock, provides a highly accurate timing event. The overall scheme is that a number is selected and loaded into the timer. The timer counts from this number up to 255 and rolls over. Whenever it rolls over, it generates an interrupt. The interrupt service routine reloads the same number into the timer, executes any time-critical activities that may be required, and then returns to the program. The cycle then repeats, with the counter counting up from the number that was loaded to 255, and rolls over, generating another interrupt. The interrupt, then, is occurring on a regular basis when each time period has elapsed. The number loaded into the counter determines the length of the period. The lower the number, the longer it will take the timer to reach to 255 and roll over, and the longer the period of the tick will be.

As an example we will generate a 1 second tick as a time base for a real time clock.

For a timer to be used as a tick, the first necessary task is to determine the number that is loaded into the timer each time the interrupt occurs. We want the program to generate a tick every second. In this program we use a 16MHz clock and we set the prescaler to clk/256.

16/MHz/256 = 62.500 KHz = 16µs

This shows that every 16µs another clock pulse will be applied to Timer 0. Timer 0 is an 8-bit timer/counter, and so it can count up to 256 such periods before it rolls over. By using 250 coount this will give a time period of:

250 x 16µs = 4ms

Therefore, the counter reload number would be as follows:

256 x 250 = 6

This means that the interrupt service routine (ISR) will be executed once every 4 milliseconds. A global variable will be used to count to 250 to produce the entire 1 second time period:

4ms x 250 = 1s


SOFTWARE EXAMPLE

The software code contains all of the concepts discussed above. The timer/counter register itself, timer counter 0 (TCCNT0), is reloaded with the value 6 each time the ISR executes so that it can once again count up 250 steps to reach 255 and roll over. A global variable called “time_count” is used to keep track of the number of times that the interrupt service routine is executed by incrementing it each time the ISR is executed. “time_count” is both incremented and checked inside the expression of the if statement. When “time_count” reaches 250, the global variable is incremented and “time_count” is reset to zero to count up for the next 1 second period. With the 1`second time interval the real time clock can be made. In this program the real time clock is shown on a LCD display.

 

// program name: timer0_ovf_isr
// date: 2014.08.25
// target device: atmega8/atmega328p
// target: 1s interval
// author: www.avrprojects.net
// compiler: WINAVR GCC
// timero overflow interrupt service routine
// clk= 16MHz/256 = 62,500kHz = 16uS * 250 ticks = 4ms * 250 = 1s interval
#include <avr/io.h>
#include <util/delay.h>
#include <util/lcd.h>
#include <avr/interrupt.h>
unsigned char time_count;
int second=0;
int minute=19;
int hour=11; /// Timer 0 overflow interrupt service routine ISR(TIMER0_OVF_vect){//set timer to 256-250 = 6 TCNT0=6; ++time_count;if(time_count==250) {time_count=0;// set to 0 second++;// increase second if(second==60) {second=0; minute++; if(minute==60) {minute=0; hour++; if(hour==25) {hour=0; } } } }
} int main(void){

LCDini(); //set timer 0 prescaler to clk/256*/ TCCR0=0b00000100;// enable Timer 0 overflow interrupt*/ TIMSK=0x01;sei(); LCDgoto(0,0);LCDtxt("Interrupt timer0 OVF");
LCDgoto(0,1);LCDtxt(" Real Time Clock");
LCDgoto(0,3);LCDtxt("www.avrprojects.net"); while(1) { LCDgoto(6,2); if(hour<10) {LCDtxt("0"); LCDint(hour);} elseLCDint(hour); LCDtxt(":"); if(minute<10) {LCDtxt("0"); LCDint(minute);} elseLCDint(minute); LCDtxt(":"); if(second<10) {LCDtxt("0"); LCDint(second);} elseLCDint(second); }
}

HARDWARE

In this example the ATMEGA328 board is used. It is connected to a LCD 20x4 display which is connected to PORTD. The display shows the real time clock. As the clock source for the µ-controller an external X-tal is used that is connected to XTAL1 and XTAL2. This gives very accurate clock ticks. See the schemetic below.