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
}
}
}
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
#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
#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:
4. Circuit:
https://youtu.be/9X7aLHoR-aE
#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:
No comments:
Post a Comment