Time delay using timer 0 without inbuild functions in Arduino

Many times we need to use time delay in Arduino program. Arduino time delay builtin functions such as delay(), micro() and milli() are available but sometimes you need to or want to write your own time delay code. And in some cases this is necessary. For example say you need to count external events. Arduino has three timers called Timer0, Timer1 and Timer2 but Timer 0 is the only timer which can count external events. Suppose that you are using other libraries as well in your program such as LiquidCrystal library for LCD display. Then you are in trouble because the LCD liquidcrystal library uses the delay() function which uses the Timer 0. So it means you cannot use it for counting external events. That means you cannot use the LCD library and you have to write your own code for LCD which does not use the delay() function/uses the Timer 0. This is one example scenario where you have to write your own time delay function. Here it is shown how to create time delay using any timers in Arduino.


Time delay using Timer 0 in Arduino

To understand how the time delay is created in Arduino we have to know how the atmega328 microcontroller timer works Arduino uses Atmega328p microcontroller. The following shows the block diagram of Arduino/ATmega328p mirocontroller Timer 0.

Arduino Timer 0 block diagram

When creating time delay, a count value is loaded into the TCNT0 register(n=0 in the above diagram). When the count value is loaded and the timer 0 is turned on, its starts counting from 0 upto the count value. When it reaches the count value then the overflow flag TOV0 is set. When the TOV0 is set we stop the timer 0 . In the program code, we monitor this TOV0 flag to know that the count value has reached and restart the timer. This is called Normal mode of operation. This is the overall picture of what happens when we create time delay. 

Now what count value is to be loaded is depends upon what time delay we want. For example if we want time delay of 1ms then the count value is given by the following equation,

\(C = 256- number\space of \space clocks \space reqd.\)

where, \(number\space of \space clocks \space reqd. = \frac{time \space delay \space required(T_d)}{Time \space Period \space of \space CPU \space clocks}\)

and \(Time \space Period \space of \space CPU \space clocks = \frac{N}{F_{CPU}}\), where N is the prescaler

If we are using 8MHz crystal oscillator then \(F_{CPU}=8MHz\) and if we are using prescaler of 1024 then N=1024.This gives us the time period of CPU as,

\(Time \space Period \space of \space CPU \space clocks = \frac{1024}{8MHz}=128 \mu s\)

Then the number of clocks required is,

 \(number\space of \space clocks \space reqd. = \frac{1ms}{128 \mu s} \simeq 8\)

So that the count value(C) is,

 \(C = 256-8=248\)

So if we load 248 into the TCNT0 resister, start the timer, when the overflow flag TOV0 is set we have a time delay of 1ms.

There is alternative equation of the above which is,

\(C = 256 -\frac{ F_{CPU}}{NF_d}\)

where, \(F_d\) is the frequency of the time delay

In the above example, the frequency \(F_d\) is,

\(F_d=\frac{1}{T_d}=\frac{1}{1ms}=1KHz\)

So,

 \(C = 256 -\frac{ F_{CPU}}{NF_d}= 256 - \frac{8MHz}{1024 \times 1KHz} = 256 - 8 =248\)

This value of count C can be easily calculated using the Timer 0 time delay online calculator in normal mode.  

The pre-scalar value is set using the TCCR0(TCCR0A,TCCR0B) register whose content is shown below.

TCCR0 register

Here we are only concerned with the clock CS02, CS01 and CS00 bits in the TCCR0B register whose  value determines the value of the pre-scalar N.

clock select bits

So the TCCR0B register should be loaded with value 00000101 for N=1024. The CPU clock frequency of 8MHz is divided by 1024 to get clock frequency of 7.8KHz into the Timer 0.

Finally we need to monitor the timer 0 overflow flag TOV0 which is located in the TIFR0(Timer Interrupt Flag Register 0).

TIFR0

Programming Time Delay with Timer 0 for Arduino

The following is the Arduino program to create a time delay of 1ms using Timer 0. The following function T0delayOnems() is the routine for creating 1ms delay. 


void T0delayOnems(){
    //setup Timer 0
    TCNT0 = 248;		//load count value for 1ms time delay
   TCCR0A = 0x00;
   TCCR0B = 0b00000101;	//normal mode with 1024 pre-scalar
     
   while(!(TIFR0 & (1<<TOV0)));	//wait until TOV0 flag is set
   TCCR0B = 0;		//turn off timer 0
   TIFR0 |= (1<<TOV0);	//clear TOV0 flag
}

In the above code, the count value of 248 for 1ms time delay is loaded into the TCNT0 register, then the TCCR0A and TCCR0B register are configured for normal mode with 1024 pre-scalar. After that we monitor the timer overflow flag TOV0 and when it is set we know that the count value has reached and we stop the timer by clearing the TCCR0B register and setting the TOV0 flag to high(because when the timer reaches the count value it is set to low).

We can use this 1ms delay to create any desired number of milli second time delay usin another function T0delayms() illustrated below.


void T0delayms(int n){   
   for(int i = 0; i <= n; i++){
    T0delayOnems();
   }
}

Now the following shows program a led blink program with 100ms delay. The 100ms delay is created using the above two functions.


#define LED PD3

void T0delayOnems(void);
void T0delayms(int n);


int main()
 { 
   DDRD |= (1<<LED);
	
   while (1){
		PORTD ^= (1<<LED);
		T0delayms(100);
	}
   return 0;
 }


void T0delayOnems(){
    //setup Timer 0
    TCNT0 = 248;		//load count value for 1ms time delay
   //TCCR0A = 0x00;
   TCCR0B = 0b00000101;	//normal mode with 1024 pre-scalar
     
   while(!(TIFR0 & (1<<TOV0)));	//wait until TOV0 flag is set
   TCCR0B = 0;		//turn off timer 0
   TIFR0 |= (1<<TOV0);	//clear TOV0 flag
}

void T0delayms(int n){   
   for(int i = 0; i <= n; i++){
    T0delayOnems();
   }
}

So this tutorial showed how to program Arduino to use Timer 0 to create time delay. The code works for ATmega328p microcontroller because Arduino uses this microcontroller. With only register name modification this code also works for ATmega32A. For programming timer 0 time delay with ATmega32A microcontroller see the tutorial Atmega32A Timer Counter Tutorial Examples.

Post a Comment

Previous Post Next Post