The Timer Registers
To set a timer, you need to fiddle with several
registers. The following registers set up the clock source,
pre-scaling, and what the timer is used for. Each timer will
have its own unique set of registers. They will all use this
naming convention; just change the number to match the
Listing 1: Setting Up the Timer.
TIFR2 = 0;
TCCR2A = 0x02;
TCCR2B = 0x01;
TCNT2 = 0;
TIMSK2 |= (unsigned char)_BV(OCIE2A);
TIMSK2 |= (unsigned char)(1 <<OCIE2A);
OCR2A = 160;
TCCR2A: Timer/Counter Control Register A. Configures
PWM configuration on OC2A/OC2B pins, if we use them
TCCR2B: Timer/Counter Control Register B. Configures
Timer 2 pre-scale settings and a little more of the PWM
settings, if used.
TCNT2: Timer/Counter Register. This holds the current
ASSR: Asynchronous Status Register. Allows selection
of external clock sources.
These next registers are used to match PWM periods —
more on that later; they aren’t needed if you are just using
3). Use the internal clock with no prescale. Table 17-9
shows the prescale settings. Use other settings if
you want a slower clock.
4). Clear the timer to zero; start from a known place.
5). Here we set the interrupt. A timer just running by
itself is useful for some things; don’t use interrupts
if you don’t need them. Here we will use the timer
match to fire an interrupt (more on that later). I’ve
shown two ways to set a bit in a register.
6). 160 = 10 µs (microseconds) is the timer match with
a 16 MHz system clock. I did this because it was a
good value to use for controlling an RC servo pulse.
OCR2A: Output Compare Register 2A. Match value for
PWM on OC2A pin.
OCR2B: Output Compare Register 2B. Match value for
PWM on OC2B pin.
This next set of registers allow us to set interrupts on
the timer conditions and check for interrupt flags.
TIMSK2: Timer/Counter Interrupt Mask Register.
Configures the type of interrupt (if any) you want to have
on PWM or Timer conditions.
Interrupt Flag Register. We can
look here for flags set by
By now you’re thinking, “Why use an interrupt?” There
are good reasons for your timer to cause an interrupt. One
is to provide a background ticker for timing your program. I
find that such a timer is handy for timing state machines
and checking for timeouts in various places in the program.
Every time the interrupt goes off, you can increment a large
counter in your program. In this way, you can check timing
for many things without blocking program flow. Listing 2
shows what the ISR for just such a timer might look like.
My ISR does two things: it controls the position of an
RC servo (match count), and it handles my system timer tic
(1_1ms) at a 1 ms resolution. Handy, isn’t it? If all you
Listing 2: Timer ISR.
Setting Up a Timer
10 microsecond ISR on TIMER2, a 8 bit clock
We are going to start by just
setting up a timer — not PWM —
so these settings will reflect that.
Listing 1 shows the init routine.
I’ll comment on what was done.
// The single servo used
if (t_10us == 100)
// 1ms background tic
t_10us = 0;
1). Always clear your flags
before you turn something
on, especially interrupts.
2). Have the timer match on
the OC2A setting. Table 17-
8, mode 2, CTC is the
counter/timer clock match
on OCRA. When this match
occurs, the clock is cleared
back to zero to start over.
match++; // increment every 1
if (match > next_pulse)
SPIN = 0; // drop servo bit
SPIN = 1; // raise servo pin high
if (match > 1900)
next_pulse = servo;
match = 0; // restart servo timer
SERVO 12.2011 15