Advanced Coding Timers
Advanced Coding Timers
• The timer can be programmed by some special registers. You can configure the prescaler for the timer, or
the mode of operation and many other things.
• The Arduino board is based on the Atmel AVR ATmega168 or the ATmega328. These chips are pin
compatible and only differ in the size of internal memory. Both have 3 timers, called Timer0, Timer1 and
Timer2. Timer0 and Timer2 are 8bit timer, where Timer1 is a 16bit timer.
• The most important difference between 8bit and 16bit timer is the timer resolution. 8bits means 256 values
(two to the power of 8) where 16bit means 65536 values (two to the power of 16) which is much higher
resolution.
• The Arduino Mega series is based on the Atmel AVR ATmega1280 or the ATmega2560. They are almost
identical to previous chips but only differs in memory size. These chips have 6 timers. First 3 timers (Timer 0,
Timer1 and Timer2) are identical to the ATmega168/328. Timer3, Timer4 and Timer5 are all 16bit timers,
similar to Timer1.
• All timers depends on the system clock of your Arduino system. Normally the system clock is 16MHz, but
the Arduino Pro 3/3V is 8Mhz, so be careful when writing your own timer functions.
• The timer hardware can be configured with some special timer registers. In the Arduino firmware, all timers
were configured to a 1kHz frequency and interrupts are generally enabled.
4
Timer Concepts
Since childhood, we have been coming across the following formula 1
Now suppose, we need to flash an LED every 1 ms. This implies that its frequency is 1/1ms = 1000 Hz. Now
let’s assume that we have an external crystal XTAL of 16 MHz. Hence, the CPU clock frequency is 16 MHz.
Now, as I said that the timer counts from 0 to TOP. For an 8-bit timer, it counts from 0 to 255 whereas for a
16-bit timer it counts from 0 to 65535. After that, they overflow. This value changes at every clock pulse.
Let’s say the timer’s value is zero now. To go from 0 to 1, it takes one clock pulse. To go from 1 to 2, it takes
another clock pulse. To go from 2 to 3, it takes one more clock pulse. And so on. For F_CPU = 16 MHz, time
period T = 1/16M = 62.5 ns. Thus for every transition (0 to 1, 1 to 2, etc.), it takes only 62.5 ns!
Now, as stated above, we need a delay of 1 ms. This maybe a very short delay, but for the microcontroller
which has a resolution of 62.5 ns, its quite a long delay! To get an idea of how long it takes, let’s calculate the
timer count from the following formula 2
Substitute Required Delay = 1 ms and Clock Time Period = 62.5 ns, and you get Timer Count = 16000. Can you
imagine that? The clock has already ticked 16000times to give a delay of only 1 ms! Now, to achieve this, 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.
Prescaler how do we actually reduce the frequency? This technique of frequency division is called prescaling.
We do not reduce the actual F_CPU. The actual F_CPU remains the same (at 16 MHz in this case). So basically,
we derive a frequency from it to run the timer. Thus, while doing so, we divide the frequency and use it.
There is a provision to do so in AVR by setting some bits.
Formula 1 Formula 2
5
Timer Overflow
Timer overflow means the timer has reached is limit value. When a timer overflow
interrupt occurs, the timer overflow bit TOVx will be set in the interrupt flag register
TIFRx. When the timer overflow interrupt enable bit TOIEx in the interrupt mask register
TIMSKx is set, the timer overflow interrupt service routine ISR(TIMERx_OVF_vect) will be
called.
Timer Overflow
Timer Registers 9
You can change the Timer behavior through the timer register. The most important timer registers are:
TCCRx - Timer/Counter Control Register. The prescaler can be configured here.
10
Cont. Timer Registers
The Output Compare Registers contain a 16-bit value that is continuously compared with
the counter value (TCNT1). A match can be used to generate an Output Compare
interrupt, or to generate a waveform output on the OC1x pin.
The Output Compare Registers are 16-bit in size. To ensure that both the high and low
bytes are written simultaneously when the CPU writes to these registers, the access is
performed using an 8-bit temporary High Byte Register (TEMP). This temporary register is
shared by all the other 16-bit registers.
12
Cont. Timer Registers
• ICRx - Input Capture Register (only for 16bit timer)
The Input Capture is updated with the counter (TCNT1) value each time an event occurs
on the ICP1 pin (or optionally on the Analog Comparator output for Timer/Counter1).
The Input Capture can be used for defining the counter TOP value.
The Input Capture Register is 16-bit in size. To ensure that both the high and low bytes
are read simultaneously when the CPU accesses these registers, the access is performed
using an 8-bit temporary High Byte Register (TEMP). This temporary register is shared by
all the other 16-bit registers.
13
Cont. Timer Registers
• TIMSKx - Timer/Counter Interrupt Mask Register. To enable/disable timer interrupts.
Bit 7, 6 – Reserved
Bit 5 – ICIE1: Timer/Counter1, Input Capture Interrupt Enable
Bit 4, 3 – Reserved
Bit 2 – OCIE1B: Timer/Counter1, Output Compare B Match Interrupt Enable
Bit 1 – OCIE1A: Timer/Counter1, Output Compare A Match Interrupt Enable
Bit 0 – TOIE1: Timer/Counter1, Overflow Interrupt Enable
14
Cont. Timer Registers
• TIFRx - Timer/Counter Interrupt Flag Register. Indicates a pending timer interrupt.
Bit 7, 6 – Reserved
Bit 5 – ICF1: Timer/Counter1, Input Capture Flag
Bit 4, 3 – Reserved
Bit 2 – OCF1B: Timer/Counter1, Output Compare B Match Flag
Bit 1 – OCF1A: Timer/Counter1, Output Compare A Match Flag
Bit 0 – TOV1: Timer/Counter1, Overflow Flag
Clock select and Timer Frequency 15
• Clock select and timer frequency
Different clock sources can be selected for each timer independently. To calculate the timer frequency (for example 2Hz
using timer1) you will need:
• CPU frequency 16Mhz for Arduino
• maximum timer counter value (256 for 8bit, 65536 for 16bit timer)
• Divide CPU frequency through the chosen prescaler (16000000 / 256 = 62500)
• Divide result through the desired frequency (62500 / 2Hz = 31250)
• Verify the result against the maximum timer counter value (31250 < 65536 success) if fail, choose bigger prescaler.
Timer Overflow
Timer overflow means the timer has reached is limit value.
When a timer overflow interrupt occurs, the timer overflow
bit TOVx will be set in the interrupt flag register TIFRx. When
the timer overflow interrupt enable bit TOIEx in the interrupt
mask register TIMSKx is set, the timer overflow interrupt
service routine ISR(TIMERx_OVF_vect) will be called.
PWM Technique
Cont. Timer Modes 21
PWM Generation
The simplest way to generate a PWM signal is by comparing
the a predetermined waveform with a fixed voltage level as
shown in the Figure.
In the diagram shown above, we have a predetermined
waveform, sawtooth waveform. We compare this waveform
with a fixed DC level. It has three compare output modes of
operation:
Inverted Mode – In this mode, if the waveform value is
greater than the compare level, then the output is set high,
or else the output is low. This is represented in figure A
above.
Non-Inverted Mode – In this mode, the output is high
whenever the compare level is greater than the waveform
level and low otherwise. This is represented in figure B
above.
Toggle Mode – In this mode, the output toggles whenever
there is a compare match. If the output is high, it becomes
low, and vice-versa.
PWM Technique
Cont. Timer Modes 5
22
Timer Concepts - Revisited
In this section, we will revise some important and necessary
concepts related to timers. Consider the following timer diagram.
We are very well aware that the AVR provides us with an option
of 8 and 16 bit timers. 8bit timers count from 0 to 255, then back
to zero and so on. 16bit timers count from 0 to 65535, then back
to zero. Thus for a 8bit timer, MAX = 255 and for a 16bit timer,
MAX = 65535.
The timer always counts from 0 to TOP, then overflows back to
zero. In figure A shown above, TOP = MAX. Now, I guess you all
are familiar with timers in CTC Mode, in which you can clear the
timer whenever a compare match occurs. Due to this, the value
of TOP can be reduced as shown in figure B. The yellow line
shows how the timer would have gone in normal mode. Now, the
CTC Mode can be extended to introduce variable TOP as shown in
figure C (however there isn’t any practical utility of this).
TOP never exceeds MAX. TOP <= MAX.
Now that you are aware of the terminologies of TOP, BOTTOM
and MAX, we can proceed to the different modes of operation.
Timer Technique
23
Cont. Timer Modes
Fast PWM Mode
Consider the following diagram.
• In simple terms, this is Fast PWM! We have a
sawtooth waveform, and we compare it with a fixed
voltage level (say A), and thus we get a PWM output
as shown (in A). Now suppose we increase the
compare voltage level (to, say B). In this case, as we
can see, the pulse width has reduced, and hence
the duty cycle. But, as you can see, both the pulses
(A and B) end at the same time irrespective of their
starting time.
• In this mode, since sawtooth waveform is used, the
timer counter TCNTn (n = 0,1,2) counts from
BOTTOM to TOP and then it is simply allowed to
overflow (or cleared at a compare match) to
BOTTOM.
Fast PWM Technique
24
Cont. Timer Modes
Phase Correct PWM Mode
Now have a look at the following diagram.
• Here instead of a sawtooth waveform, we have
used a triangular waveform. Even here, you can see
how PWM is generated. We can see that upon
increasing the compare voltage level, the duty cycle
reduces. But unlike Fast PWM, the phase of the
PWM is maintained. Thus it is called Phase
Correct PWM.
• By visual inspection, we can clearly see that the
frequency of Fast PWM is twice that of Phase
Correct PWM.
ISR(TIMER1_OVF_vect)
{ // interrupt service routine that wraps a user defined function supplied by attachInterrupt
TCNT1 = 34286; // preload timer
digitalWrite(ledPin, digitalRead(ledPin) ^ 1);
}
void loop() { // your program here... }
30
Examples of Timer Interrupts
#define ledPin 13
Blinking LED with compare match void setup()
interrupt (CTC) {
pinMode(ledPin, OUTPUT);
uses the timer1 in CTC mode and // initialize timer1
the compare match interrupt to noInterrupts(); // disable all interrupts
toggle a LED. The timer is TCCR1A = 0;
configured for a frequency of 2Hz. TCCR1B = 0;
TCNT1 = 0;
The LED is toggled in the interrupt
OCR1A = 31250; // compare match register 16MHz/256/2Hz
service routine. TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
}