You are on page 1of 4

AVR Timers TIMER1

Hello folks! Welcome back! In this tutorial, we will come across TIMER1 of the AVR. I
hope that you have read and understood the previous posts:
Introduction to AVR Timers
AVR Timers TIMER0

So basically, in this tutorial, we will do whatever we did in the previous one. In the TIMER0 tutorial, we
generated a timer running at the CPU frequency. We then modied the code to include prescalers, and
once again modied the code to include interrupts.

Now that you are aware of the concepts, we will deal with TIMER1 in a short and snappy way. Whatever we
did in the previous TIMER0 tutorial, we will do the same here. Thus, we will discuss only one problem
statement which will include both, prescalers and interrupts.

Once we are done with this, we can proceed to the CTC and PWM modes of operations in subsequent
posts.

Problem Statement

Okay, lets make it loud and clear. We need to ash an LED every 2 seconds, i.e. at a frequency of 0.5 Hz. We
have an XTAL of 16 MHz.

Methodology Using prescaler and interrupt

Okay, so before proceeding further, let me jot down the formula rst.

Given that we have a CPU Clock Frequency of 16 MHz. At this frequency, and using a 16-bit timer (MAX =
65535), the maximum delay is 4.096 ms. Its quite low. Upon using a prescaler of 8, the timer frequency

reduces to 2 MHz, thus giving a maximum delay of 32.768 ms. Now we need a delay of 2 s. Thus, 2 s
32.768 ms = 61.035 61. This means that the timer should overow 61 times to give a delay of
approximately 2 s.

Now its time for you to get introduced to the TIMER1 registers (ATMEGA16/32). We will discuss only those
registers and bits which are required as of now. More will be discussed as and when necessary.

TCCR1B Register

The Timer/Counter1 Control Register B TCCR1B Register is as follows.

TCCR1B Register

Right now, only the highlighted bits concern us. The bit 2:0 CS12:10 are the Clock Select Bits of TIMER1.
Their selection is as follows.

Clock Select Bits Description

Since we need a prescaler of 8, we choose the third option (010).

TCNT1 Register

The Timer/Counter1 TCNT1 Register is as follows. It is 16 bits wide since the TIMER1 is a 16-bit register.

TCNT1H represents the HIGH byte whereas TCNT1L represents the LOW byte. The timer/counter value is
stored in these bytes.

TIMSK Register

TCNT1 Register

The Timer/Counter Interrupt Mask Register TIMSK Register is as follows.

TIMSK Register

As we have discussed earlier, this is a common register for all the timers. The bits associated with other
timers are greyed out. Bits 5:2 correspond to TIMER1. Right now, we are interested in the yellow bit only.

Other bits are related to CTC mode which we will discuss later. Bit 2 TOIE1 Timer/Counter1 Overow
Interrupt Enable bit enables the overow interrupt of TIMER1. We enable the overow interrupt as we are
making the timer overow 61 times (refer to the methodology section above).

TIFR Register

The Timer/Counter Interrupt Flag Register TIFR is as follows.

TIFR Register

Once again, just like TIMSK, TIFR is also a register common to all the timers. The greyed out bits correspond
to dierent timers. Only Bits 5:2 are related to TIMER1. Of these, we are interested in Bit 2 TOV1

Timer/Counter1 Overow Flag. This bit is set to 1 whenever the timer overows. It is cleared (to zero)
automatically as soon as the corresponding Interrupt Service Routine (ISR) is executed. Alternatively, if
there is no ISR to execute, we can clear it by writing 1 to it.

Code

Now that we are aware of the methodology and the registers, we can proceed to write the code for it. To
learn about I/O port operations in AVR, view this. To know about bit manipulations, view this. To learn how
to use AVR Studio 5, view this. To learn how this code is structured, view the previous TIMER0 post.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43

#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

44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59

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
}

So folks, this is how to apply the basic timer concepts for TIMER1. Please note that if you learn the basics,
everything will be easy. If you nd yourself struggling with the code, then please visit the TIMER0 tutorial,
clear your concepts and give it a try again. If still you dont get it, I will be glad to help you! :)

In my next post, we will learn how to apply the same concepts to TIMER2. It is, once again, an 8-bit timer.

Thus all the TIMER2 registers are similar to TIMER0. After that, we move towards the interesting part, the
Clear Timer on Compare (CTC) mode!

You might also like