Featured post

Objectives and content

Sunday 29 May 2016

Timers

Timer fundamental
1.      Timer- a register the value of which increases/decreases automatically
2.      Timers are of two types: 8-bit and 16-bit timers.
3.      8-bit timer- capable of counting 2^8=256 steps from 0 to 255
4.      16 bit timer- capable of counting 2^16=65536 steps from 0 to 65535.
5.      Timer/counter overflow- after reaching the final count it returns to its initial value of zero
6.      In ATMEGA32
a.       TIMER0 – 8-bit timer
b.      TIMER1 – 16-bit timer
c.       TIMER2 – 8-bit timer
7.                  Timer is totally independent of the CPU- it runs parallel to the CPU and there is no CPU’s intervention, which makes the timer quite accurate.
8.                  Mode of operation- normal mode, CTC mode or PWM mode.
9.                  Problem- flash an LED every 10 ms. frequency is 1/10ms = 100 Hz.
Soln. let we have an external crystal XTAL of 4 MHz.  F_CPU = 4 MHz, time period T = 1/4 us = 0.00025 ms. Thus for every transition (0 to 1, 1 to 2, etc), it takes only 0.00025 ms! timer counts from BOTTOM=0 to TOP i.e. for an 8-bit timer, it counts from 0 to TOP =255 whereas for a 16-bit timer it counts from 0 to TOP =65535.  After that, they overflow.  Here required Delay = 10 ms and Clock Time Period = 0.00025 ms, therefore Timer Count = (10/0.00025)-1=39999.  Here we definitely cannot use an 8-bit timer (as it has an upper limit of 255, after which it overflows). Hence, we use a 16-bit timer (which is capable of counting up to 65535) to achieve this delay.
10.               The Prescaler –
a.       Reduces effective clock frequency for the timer
b.      Increases clock interval
c.       Reduces count for the same delay
11.              Assuming F_CPU = 4 MHz and a 16-bit timer (MAX = 65535), and substituting in the above formula, we can get a maximum delay = 65535X(1/4)us = 16.384 ms. Now what if we need a greater delay, say 20 ms use prescaler (CS02:01:00=010) to decrease the F_CPU from 4 MHz to 0.5 MHz (i.e. 4MHz/8=500 kHz), then the clock time period increases to 1/500k = 0.002 ms. Now if we substitute Required Delay = 20 ms and Clock Time Period = 0.002 ms, we get Timer Count = 9999 (possible using using a 16-bit timer). At this frequency, a maximum delay of 65535X(1/0.5)us = 131.072 ms can be achieved.
Note: Here resolution i.e. clock interval has been decreased (means the accuracy has been decreased) from 0.00025 ms to 0.002 ms. Therefore each tick will take 0.002 ms. Earlier, it was possible to measure duration like 0.1125 ms accurately (0.1125/0.00025 = 450), but now (0.1125/0.002 = 56.25). The new timer can measure 0.112 ms by the overflow count 56. For remaining overflow count 0.25 i.e. delay=0.25X0.002=0.5 ms set the clock without prescaling value i.e. 4MHz. then overflow count= .5 ms X 4 MHz=2000.
12.              The value of the counter is stored in TCNT register and increases/decreases automatically. Data can be both read/written from this register.
13.              TCCR register holds the control bits such as clock select bits
Expt-1
1.      Title: Study on Timer 0 without prescaler
2.      Components required:
Sl. No.
Category
Item name/value
Quantity
Circuit diagram
1
IC
ATMEGA32
1

2

7805
1
3
Resistor
10K        
1
4

330R
1
5
Capacitor
0.1uf
2
6

22pf
2
7

10uf, 24Volt
1
8
Crystal Oscillator
16MHz
1
9
LED
Green
1
10
Battery
9Volt
1

3.      Procedure to code:
a.       Assign the clock frequency
b.       Include the header files avr/io.h
c.        Assign port C0 pin as output port to connect LED
d.       Initialize timer T0
                                                                           i.      No prescaling
                                                                          ii.      Initialize with 0 count
e.        Check for timer count crossing beyond 190
f.        If no goto step ‘g’
g.        Complement the logic value of port C0 pin
h.       Initialize with 0 count
i.        Go to step ‘e’
4.      Code:

#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
void timer0_init()
{
// set up timer with no prescaling
TCCR0 |= (1 << CS00);
// initialize counter
TCNT0 = 0;
}
int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);
// initialize timer
timer0_init();
// loop forever
while(1)
{
// check if the timer count reaches 191
if (TCNT0 >= 191)
{
PORTC ^= (1 << 0); // toggles the led
TCNT0 = 0; // reset counter
}
}

}
5.      Timer Simulation:




Expt-2
1.      Title: Study on Timer 0 with prescaler

2.      Procedure to code:
a.       Assign the clock frequency
b.      Include the header files avr/io.h
c.       Assign port C0 pin as output port to connect LED
d.      Initialize timer T0
                                                                          i.      Prescaling clock frequency divided by 1024
                                                                        ii.      Initialize with 0 count
e.       Check for timer count crossing beyond 124
f.       If no goto step ‘g’
g.       Complement the logic value of port C0 pin
h.      Initialize with 0 count
i.        Go to step ‘e’
3.      Code:


#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
void timer0_init()
{
// set up timer with prescaler = 1024
TCCR0 |= (1 << CS02)|(1 << CS00);
// initialize counter
TCNT0 = 0;
}
int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);
// initialize timer
timer0_init();
// loop forever
while(1)
{
// check if the timer count reaches 124
if (TCNT0 >= 124)
{
PORTC ^= (1 << 0); // toggles the led
TCNT0 = 0; // reset counter
}
}
}
4.      Timer Simulation:


Expt-3:
1.                   Title: Flash an LED every 50 ms with an XTAL of 16 MHz.
2.                   Procedure Using Interrupts: CPU frequency 16 MHz, gives maximum delay with prescaler 1024 is 16.32 ms = (255/(16/1024(prescaler)). The concept here is that the hardware generates an interrupt every time the timer overflows. Since the required delay is greater than the maximum possible delay, obviously the timer will overflow. If the prescaler, be 256, it should take 255/(16/256) ms = 4.08 ms per calculation for the timer to overflow. Now as soon as the timer overflows, an interrupt is fired and an Interrupt Service Routine (ISR) is executed. Now, 50 ms ÷ 4.08 ms = 12.255. Thus, in simple terms, by the time the timer has over flown 12 times, 12*4.08=48.96 ms would have passed. After that, when the timer undergoes 13th iteration, it would achieve a delay of 50 ms. Thus, in the 13th iteration, we need a delay of 50 – 48.96 = 1.04 ms. At a frequency of 62.5 kHz (prescaler = 256), each tick takes 0.016 ms. Thus to achieve a delay of 1.04 ms, it would require 1.04*62.5 = 65 ticks. Thus, in the 13th iteration, we only allow the timer to count up to 65, and then reset it.
3.                   The Timer/Counter Interrupt Mask (TIMSK) Register: It is a common register for all the three timers. For TIMER0, bits 1 and 0 are allotted. Setting the 0th bit TOIE0 to ‘1’ enables the TIMER0 overflow interrupt.
4.                   Timer/Counter Interrupt Flag Register (TIFR) – This is also a register shared by all the timers. Bits 1 and 0 are allotted for TIMER0. TOV0 bit is set (one) whenever TIMER0 overflows. This bit is reset (zero) whenever the Interrupt Service Routine (ISR) is executed. If there is no ISR to execute, we can clear it manually by writing one to it. We don’t require this in the present problem.
5.                   Enabling Global Interrupts: Calling a function named sei().
6.                   Procedure to code:
a.       declare the global variable to count the number of overflows
b.       TIMER0 overflow interrupt service routine called whenever TCNT0 overflows
c.        keep a track of number of overflows
d.       set up timer with prescaler = 256
e.        initialize counter
f.        enable overflow interrupt
g.        enable global interrupts
h.       initialize overflow counter variable
i.         connect led to pin PC0 and set it as output port
j.         initialize timer with prescaler 256
k.       check if no. of overflows = 12
l.         check if the timer count reaches 53
m.     toggles the led
n.       reset counter
o.       reset overflow counter
5.      Code:

#ifndef F_CPU
#define F_CPU 16000000UL
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
// global variable to count the number of overflows
volatile uint8_t tot_overflow;
// TIMER0 overflow interrupt service routine
// called whenever TCNT0 overflows
ISR(TIMER0_OVF_vect)
{
// keep a track of number of overflows
tot_overflow++;
}
void timer0_init()
{
// set up timer with prescaler = 1024
TCCR0 |= (1 << CS02);
// initialize counter
TCNT0 = 0;
// enable overflow interrupt
TIMSK |= (1 << TOIE0);
// enable global interrupts
sei();
// initialize overflow counter variable
tot_overflow = 0;
}
int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);
// initialize timer
timer0_init();
// loop forever
while(1)
{
// check if no. of overflows = 12
if (tot_overflow >= 12) // NOTE: '>=' is used
{
// check if the timer count reaches 53
if (TCNT0 >= 53)
{
PORTC ^= (1 << 0); // toggles the led
TCNT0 = 0; // reset counter
tot_overflow = 0; // reset overflow counter
}
}
}
}

6.      Timer Simulation:

Expt-4:
1.       Title: Flash an LED every 2 seconds with a XTAL of 16 MHz using Timer 1.
2.                   Procedure to code:
a.       Set PC0 as output
b.  To initialize Timer 1:
1.  first set up timer with prescaler = 8 i.e. set CS11
2.  Initialize counter Timer/Counter1 – TCNT1 to 0;
3.  To enable interrupt at TCNT MAX value overflow set Timer/Counter1 Overflow Interrupt Enable bit TOIE1 of the Timer/Counter Interrupt Mask Register – TIMSK
4.  Enable global interrupts with function sei();
5.  Initialize overflow counter by a global variable tot_overflow to 0 of type volatile uint8_t
c.  TIMER1 overflow interrupt service routine:
1.  Incrementing tot_overflow to count the number of overflow
2.  Check for 61 overflows i.e. 2 seconds delay (approx.)
3.  If yes:
                                      i.   XOR PC0 with 1 to toggle the connected led
                                     ii.   no timer reset required here as the timer
                                    iii.   Reset overflow counter tot_overflow to 0
d.  Write an ever ending loop for continuous operation of toggling

7.      Code:

              #include <avr/io.h>
#include <avr/interrupt.h>
// global variable to count the number of overflows
volatile uint8_t tot_overflow;
// initialize timer, interrupt and variable
void timer1_init()
{
// set up timer with prescaler = 8
TCCR1B |= (1 << CS11);
// initialize counter
TCNT1 = 0;
// enable overflow interrupt
TIMSK |= (1 << TOIE1);
// enable global interrupts
sei();
// initialize overflow counter variable
tot_overflow = 0;
}
// TIMER1 overflow interrupt service routine
// called whenever TCNT1 overflows
ISR(TIMER1_OVF_vect)
{
// keep a track of number of overflows
tot_overflow++;
// check for number of overflows here itself
// 61 overflows = 2 seconds delay (approx.)
if (tot_overflow >= 61) // NOTE: '>=' used instead of '=='
{
PORTC ^= (1 << 0); // toggles the led
// no timer reset required here as the timer
// is reset every time it overflows
tot_overflow = 0; // reset overflow counter
}
}
int main(void)
{
// connect led to pin PC0
DDRC |= (1 << 0);
// initialize timer
timer1_init();
// loop forever
while(1)
{
// do nothing
// comparison is done in the ISR itself
}
}


Timer Simulation:


CTC mode: In CTC Mode compare match is implemented in hardware. Which means that we no longer need to worry about comparing the process value with the set point every time! This will not only avoid unnecessary wastage of cycles, but also ensure greater accuracy (i.e. no missed compares, no double increment, etc). Hence, this comparison takes place in the hardware itself, inside the AVR CPU! Once the process value becomes equal to the set point, a flag in the status register is set and the timer is reset automatically. Thus CTC stands for Clear Timer on Compare.

Expt-5:
1.       Title: Flash an LED every 100 ms using a crystal of XTAL 16 MHz.
2.                   Procedure to code:
a.  Connect led to pin PC0
b.  Initialize timer
1.  Set up timer with prescaler = 64 and CTC mode
2.  Initialize counter TCNT1
3.  Initialize compare value in OCR1A
c.  Loop forever
d.  Check whether the flag bit is set
e.  If set, it means that there has been a compare match and the timer has been cleared
f.  Use this opportunity to toggle the led
g.  Clear the flag bit manually since there is no ISR to execute
h.  Clear it by writing '1' to it (as per the datasheet)

3.  Code:


#include <avr/io.h>
void timer1_init()
{
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
TCNT1 = 0;
OCR1A = 24999;
}
int main(void)
{
DDRC |= (1 << 0);
timer1_init();
while(1)
{
if (TIFR & (1 << OCF1A)) // NOTE: '>=' used instead of '=='
{
PORTC ^= (1 << 0); // toggles the led
}
TIFR |= (1 << OCF1A);
}
}



Expt-6:
4.       Title: Flash an LED every 100 milliseconds with a XTAL of 16 MHz using CTC mode.
5.                   Procedure to code:
i.  connect led to pin PC0
j.  initialize timer
k.  loop forever
l.  Initialize timer, interrupt and variable
1.  set up timer with prescaler = 64 and CTC mode
2.  initialize counter
3.  initialize compare value
4.  enable compare interrupt
5.  enable global interrupts
6.  this ISR is fired whenever a match occurs causes toggle led
m.  under ISR routine statement to toggle led
6.  Code:


#ifndef F_CPU
#define F_CPU 16000000L
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init()
{
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
TCNT1 = 0;
OCR1A = 24999;
TIMSK |= (1 << OCIE1A);
sei();
}
ISR (TIMER1_COMPA_vect)
{
PORTC ^= (1 << 0);
}
int main(void)
{
DDRC |= (1 << 0);
timer1_init();
while(1)
{
// do nothing
}
}



Expt-7
1.      Title: Connect the LED to PD5 instead of PC0 to toggle using Output Compare (OC) pins.
2.      Procedure to code:
1.      initialize timer, interrupt and variable
2.      connect led to pin PD5
3.      initialize timer
                                                                                                  i.      set up timer with prescaler = 64 and CTC mode
                                                                                                ii.      set up timer OC1A pin in toggle mode
                                                                                              iii.      initialize counter
                                                                                              iv.      initialize compare value
4.      loop forever
5.       
3.      Code:


#ifndef F_CPU
#define F_CPU 16000000L
#endif
#include <avr/io.h>
#include <avr/interrupt.h>
void timer1_init()
{
TCCR1B |= (1 << WGM12)|(1 << CS11)|(1 << CS10);
TCCR1A |= (1 << COM1A0);
TCNT1 = 0;
OCR1A = 24999;
}
int main(void)
{
DDRD |= (1 << 5);
timer1_init();
while(1)
{
}
}

4. Circuit:

5. Simulation:

https://youtu.be/9X7aLHoR-aE


No comments:

Post a Comment