In timer section will study how a “_delay_ms( );” function actually works. We have used this function to hold the process for sometime. But how does CPU know the accurate delay timing for any process ?
In many applications we required to count the number of times an event is happened i.e. counter. There many counter registers available in microcontroller Content of counter register is incremented/decremented by triggering of clock pulses connected to counter register. This clock source will change the content of counter register. Suppose we want to count an event , then we connect the external event source to clock pin of counter register. So when this event occur , the content of counter register is incremented ; in this way, the content of counter register gives the number of times an event is occurred.
Now suppose we want to generate a delay of 100ms(millisecond) . One way is to use directly delay function i.e. ” _delay_ms(100)”. Another way is to use timer, this is efficient way of producing delay in any process as it is accurate. To produce time delays , we connect oscillator to clock pin of counter register. So , when oscillator ticks content of counter register is incremented. As a result , the content of counter register represent the number of ticks occur from the initial point where we connect the oscillator. Now if we know the time of one tick of oscillator then , we multiply the content of counter register with time of one tick to get total time delay.
Suppose we connect oscillator of frequency is 1KHz to the counter register. The time period of oscillator is 1millisecond, this means oscillator ticks every 1 millisecond. Let we want the time delay of 100ms. So when the content of counter register becomes 100 then , we get the required time delay i.e.(1msX100=100ms).
figure-A general view of Timers and Counters in microcontrollers.
‘FLAGS’ in timer plays an most important role. Suppose we have counter register of 8-bit i.e. it can store a number which can be of 8-bits. Let CPU frequency is 1MHz and we want an time delay of 50µs (microsecond). Oscillator speed is one tick every 1microsecond i.e. a time period of 1µs. We can get required time delay if we incrementing the value of counter register upto 50 and after that we clear the counter register. Here comes the role of ‘flag’. Flag will keeps on incrementing the value of counter register and if counter register has required value i.e. 50 in this case. Then , flag will set and software itself clear the value of counter register. So flag will indicate whether counter register is overflow or not.
Suppose counter register is incremented in every 1 second. Let the initial value stored in counter register is 1 then , after 20 seconds the value stored in counter register is 21. Suppose we want 51 to be stored in counter register then , after 50 clock pulses or ticking the value of counter register is clear. The instant when the value stored in counter register is 50 then , after next clock pulse the value stored in counter register is called ‘overflow’ because after this clock pulse the counter register has to be cleared.
In AVR some of timers/counters are 8-bits and some are 16-bits. There are three timers in AVR i.e. Timer0, Timer1 and Timer2. Timer0 and Timer2 are 8-bits and Timer1 is 16-bits. Here 8-bit and 16-bit only signifies that the value that an counter register can store can be of 8-bit or 16-bit long.
PROGRAMMING OF TIMERS AND REGISTERS USED:
The basic tool in timers is clock frequency. We can give clock pulses to counter register in two ways:
- INTERNAL CLOCK PULSE.
- EXTERNAL CLOCK PULSE.
By giving internal clock pulse to counter register we can make time delay generation function. And by giving external clock pulses we can make counter to count when an event is occur. We use internal crystal oscillator to give internal clock pulses or we can connect external crystal oscillator for high frequencies to use as a clock generator.
BASIC REGISTERS OF TIMERS 0 , 1 , AND 2:
In AVR , for each of the timers , there is TCNTn(timer/counter) register is available. For ATmega32 we TCNT0 , TCNT1 and TCNT2 registers. When we reset the TCNTn register it contains zero. It counts up with each pulses. The content of timers/counters can be accessed using TCNTn. To initiate a timer we have to load the value in TCNTn register and we can also read the value from TCNTn.
Each timer has TOVn(Timer Overflow) flag register. From this register we can understand whether the TCNTn register is overflown or not. When timer is overflows, TOVn flag is set.
Each timer also has the TCCRn (timer/counter control) register.This register is used for setting the different modes of operations. For example, to choose which timer is to be used whether 0 , 1 or 2 we have to put proper value in TCCRn register to choose either of the timer.
Each timer also has an OCRn(Output Compare Match) register. Suppose we want to clear the content of TCNTn register after it becomes 40. Then we load the value of OCRn register with 40. The content of TCNTn is compared with OCRn register and if they are equal OCFn flag is set and content of TCNTn is cleared.
TIMERS BASIC DIAGRAM AND OPERATIONS:
TIMER 0 PROGRAMMING:
Timer0 is 8-bit in AVR microcontroller.
TCNT0 REGISTER: It is 8-bit register also called timer/counter register.
TCCR0 REGISTER(timer/counter control register): It is 8-bit register used for control of timer0.
CS02:CS00(timer 0 clock source)- these bits in timer 0 are used to choose the clock source. If CS01:CS00=000 , then counter is stopped. If CS02-CS00 has values between 001 and 101 , the oscillator is used as clock source and and timer/counter acts as timer. And if CS02-CS00 has values between 110 and 111 , the external clock is used and it acts as counter.
WGM01:WGM00-Timer 0 can work in four different modes:
- Phase correct PWM.
- CTC mode.
- Fast PWM.
These bits are used to choose any mode from them.
TIFR(Timer/Counter Interrupt Flag) Register- It contains the Flag of different timers.
We know that timer0 is 8-bit timer so the maximum value that can be stored in this timer is 0xFF(in hex). The timer move from 0x00 to 0xFF then clears to 0x00. When timer overflows, the TOV0 flag is set and we have to clear the flag , so that when again timer overflows TOV0 flag will able to set. But to clear the flag we have to write 1 in it.
Example Program Code:
We have previously discuss that there are four types of modes in which timer operated here we discuss one of them.
TIMER0 NORMAL MODE:
In this mode , the content of timer/counter increments with each clock. It counts up until it reaches its maximum of 0xFF. When it rolls from 0xFF to 0x00 its flag is set high called TOV0. This flag can be monitored to know whether the timer overflows or not.
STEPS TO PROGRAM TIMER0 IN NORMAL MODE-
- Load the TCNT0 with any initial count value. The value can be between 0 to 255 as timer0 is of 8-bit.
- Load the value into TCCR0 register, for normal mode values of WGM00:WGM01 is 0. Then set the clock frequency by choosing values of CS02:CS01:CS00. Clock frequency is need because every clock pulse , the value of timer/counter is incremented by 1. So choosing of clock frequency is crucial step here.
- Keep monitoring the timer overflow flag (TOV0) and if this flag is set that means the timer is overflow so get out of loop.
- Clear the TOV0 flag by setting it to 1. So that when again timer overflows then TOV0 is set.
- Go back to step 1 and again load value into TCNT0.
EXAMPLE PROGRAM-Suppose we have clock source of 8MHz. We want to blink an LED after 100 second(microsecond). The led is connected to PINB1.
One way to done this program by directly using _delay_us(100);
But here we done this program by using TIMER0.
- Make PINB1 as output because LED is connected to it.
- Then make a “delay()” function which will produce an delay of 100µsec.
- Switch on LED by writing ‘1’ to PINB1 i.e. PORTB=PORTB|(1<<PINB1);
- Then call “delay()” function so that is it makes the LED switch on for 100µsec.
- Switch off LED by writing ‘0’ to PINB1-PORTB=PORTB&~(1<<PINB1);
STEPS TO MAKE “delay()” FUNCTION-
A. We have clock frequency of 8MHz. Suppose we want 1MHZ to be given to timer circuit then, we have to set some prescalars so that clock to timer circuit is equals to .
|CS02||CS01||CS00||Clock frequency to timer circuit|
We know that ,
|CS02||CS01||CS00||Clock frequency to timer circuit|
so we set value of CS02:CS00-‘010’.
B. Now the clock frequency to timer circuit is 1MHz. We want delay of 100µsec so we have to load some value in TCNT0 register so that after 100µsec this register will be overflow. But what is the value we have to introduce into TCNT0 register so that it will overflow in exactly 100µsec?
We know the time period of clock pulse i.e.1µsec. That means, every 1µsec the value of TCNT0 register is incremented by 1. The TCNT0 register move from 0 to 255 and then again to 0. So, to produce delay of 100µsec we have to make TCNT0 to overflow after 100µsec. As TCNT0 value is incremented after 1µsec if we load TCNT0 with 155 i.e.[255-100] then TCNT0 overflow after 100µsec. We can calculate value of TCNT0 by this formula-
Here we have time period of clock pulse is 1µsec and we have to produce delay of 100µsec. And maximum value of TCNT0 is 255.
So we get the value TCNT0 as follows-
Then, Load the value of TCNT0 with 155.
- Wait for timer0 overflow flag (TOV0) to be set.
- If TOV0 is set then, move out of loop and clear the TOV0 flag by writing it to ‘1’.
QUESTION-Assuming XTAL=8MHz, find the value to be loaded into TCNT0 register to get the delay of 6.25µsec?
ANSWER-Time Period of clock pulse=0.125µsec. Suppose we are using no prescalars then, the clock pulse given to timer circuit is 0.125 µsec. So every 0.125 µsec the value of TCNT0 is incremented by 1. To get delay of 6.25 µsec –
QUESTION-Assuming XTAL=8MHz, suppose we want to make a square wave of frequency 125Hz, find the value to be loaded into TCNT0? Use prescalar 256.
ANSWER–Time period of clock pulse=0.125µsec. So, every 0.125µsec the value of TCNT0 is incremented. But we have prescalar of 256 that means frequency of clock pulse given to timer circuit is 8/256MHz 0.03125MHz. Time period of clock pulse is 32µsec. We have to make square wave of frequency 125Hz i.e. time period=8msec(millisecond). We know that square wave has duty cycle of 50% so square wave will be high for 4msec which means we have to make delay of 4msec. To make delay of 4msec the value loaded into
TIMER0 CTC MODE –Clear Timer0 on Compare Match
In timer0 diagram we see OCR0 register.
In ctc mode , OCR0 register is used. As with the Normal mode , in ctc mode the timer is incremented with a clock. But it counts until the content of TCNT0 register becomes equal to the content of OCR0(compare match occurs) ; then, the timer will be cleared and the OCF0 flag will be set when the next clock is occur. The OCF0 flag is located in TIFR register.
FOR CTC MODE-
Let OCR0 contains ‘194’ so, we know that is content of TCNT0 and OCR0 becomes equal then, TCNT0 will be cleared. It can be seen in following figure.
We will see programming of CTC mode later.
TIMER 1 PROGRAMMING:
Timer1 is 16-bit timer and it has lots of capabilities. Since timer1 is of 16-bits its registers split into two bytes. These are referred to as TCNT1L (timer1 low byte) and TCNT1H (timer1 high byte). Timer 1 has also two control registers TCCR1A (timer/counter 1 control register) and TCCR1B. TOV1 flag goes high when overflow occurs. There are two OCR registers in timer1:OCR1A and OCR1B. Whenever TCNT1 equals to OCR1A , the OCF1A flag will be set on the next timer clock. And whenever TCNT1 equals to OCR1B , the OCF1B flag will be set on the next timer clock. These OCR1A and OCR1B are also of 16-bit so they are split into two bytes i.e. OCR1AH(high byte),OCR1AL(low byte) and OCR1BH,OCR1BL.
The TIFR register has initially all bits equals to ‘0’.
There is also auxiliary register ICR1 , which is used for capturing. These register is of 16-bit, splited into two bytes i.e. ICR1H and ICR1L.
THE VALUE OF TCNT1 MOVED FROM 0 TO 65535 or 0x0000 TO 0XFFFF.
WGM13:WGM12:WGM11:WGM10-These bits define the mode of operation of timer1. There are 16 modes of operations. One of them (mode 13) is reserved (NOT IMPLEMENTED).
TIMER1 IN NORMAL MODE (WGM13:WGM12:WGM11:WGM10=0000)-
In this mode, timer counts up until it reaches 0xFFFF (which is the maximum) and it rolls over from 0xFFFF to 0x0000. When the timer rolls over from 0xFFFF to 0x0000, the TOV1 flag will be set .
TIMER1 IN CTC MODE (WGM13:WGM12:WGM11:WGM10=0100)-
In mode 4( CTC mode), timer counts up until the content of TCNT1 register and the content of OCR1A (compare match occurs) are equal. After there content becomes equal the TCNT1 register will be cleared in next clock cycle. As a result of compare match OCF1A flag will be raised.
EXAMPLE-Suppose we have XTAL=8MHZ and we want to blink an LED with 100msec delay connected to PIND0, write the program code for it. Use timer1 with prescalar 1024.
We have clock frequency 8MHz. The frequency given to timer circuit is 8/1024 i.e. 0.0078125MHz. The time period of clock source given to timer circuit is 128µsec. So every 128µsec the value of TCNT1 is incremented by 1. We need time delay of 100msec so we have to load the following value into TCN1 register;
TIMER 2 PROGRAMMING:
Timer 2 is an 8-bit timer so it works in same way as timer 0 does. But there are two differences between timer0 and timer2;
- Timer 2 can be used as real time counter. To do so , we have to connect a crystal of 32.728KHz to the T0SC1 and TOSC2 pins of AVR and set the AS2 bit to ‘1’.
- In timer 0 when CS02-CS00 has values 110 or 111, timer 0 counts the external events. But in timer 2 , the multiplexer selects between the different scales of the clock. In other words, the value of CS can have different meaning for timer 0 and timer 2.
EXAMPLE: Find the value TCCR2 for if we want to program Timer2 in normal mode with a prescalar of 64 using internal clock source?
ANSWER: From above figure of TCCR2 register, we can calculate value of TCCR2 register as follows-
PROGRAM CODE – PROGRAM TO BLINK AN LED WITH AN DELAY OF 10mSEC USING TIMER 2 IN NORMAL MODE . GIVEN XTAL=1MHz , PRESCALAR=128 AND LED CONNECTED TO PINC0.
In previous section, we discussed about the timers. In case of timer, the value of counter register incremented with clock pulse and we are able to produce time delays. With the use of timer we also generated square waves of any time period. But consider the situation that we have square wave outside the AVR microcontroller but we don’t know its time period. Can we able to find out the time period of any square wave outside the AVR ? The answer is YES. With the use of counter we can find the time period of any square wave outside the environment of AVR microcontroller by just using counter programming.
In case of counter, the pulse outside the environment will increment the TCNTx register with every clock pulse. Note that the registers used in counter mode , OCR0,TCCR0,TCNT0,TCCR1A etc. are remain same as discussed in timers section.
CS00, CS01 AND CS02 BITS IN TCCR0 REGISTER-
We know that CS (clock selector) bit used to decide the clock frequency given to timer circuit. If CS00-02 is between 1 and 5, timer get pulse from crystal oscillator. In contrast , when CS00-02 is in between 6 and 7, the timer is used as counter and get its pulse coming from a source outside the AVR chip. When CS00-02 is 6 or 7 , TCNT0 counter counts up as pulses are fed from T0 pin( Timer/Counter 0 External Clock Input).
In ATmega16/32, T0 is alternative function of PINB0. In case of timer 0, when CS00-02 is 6 or 7 , pin T0 provides the clock pulse and counter counts up for every clock pulse coming from that pin. Similarly for timer1, when CS00-02 is 6 or 7, the clock pulses coming in from pin T1 (Timer/Counter 1 External Clock Input) makes the TCNT1 counter to counts up. When CS12:10 is 6, the counter counts up on the negative(falling) edge. When CS12:10 is 7, the counter counts up on the positive(rising) edge. In ATmega16/32, T1 pin is alternative function PINB1.
EXAMPLE-Assuming 1Hz external clock source is fed to T1 pin, use the Timer1 and count the number of times rising edge of this external clock source occurs. Display the result to PORTC.
ALGORITHM FOR PROGRAM-
- Make the PORTC as output.
- Make pin PB1( T1 ) as input pin. At pinT0 the external clock source is connected.
- Load the initial value in TCNT1 register as 0.
- Set the value of TCCR1B register to set clock source as external clock with rising edge.
- Wait for TCNT1 to overflow. In same time, put the value of TCNT1 to PORTC.
- And when TOV1 flag is raised then , clear the TOV1 flag by writing ‘1’ to it.
- When flag is set then, make PORTC=0x00 so that previous value on PORTC doesn’t collide with it present value.