2.11. Timers

A timer is actually a counter that increments the value in a register with a fixed frequency. The ATmega328P has a clock speed of 20MHz an supplies two 8-bit timers and a 16-bit timer. An 8-bit timer can count up to 28-1=255, whereas a 16-bit timer can count from 0 to 216-1=65535.

How do timers work?

You might recall from your physics class that the inverse of frequency is a period. In this respect we will write our first equation:

(1)

What equation (1) tells us is that a higher the frequency will result in small periods of time. That means that our timer won't be able to measure big intervals of time because each increment will be associated with a small period. That is why each timer has associated a prescaler which divides the microcontroller frequency with fixed values to better suit the programmer's needs.

Figure 1. Timer flow of actions.

In Figure 1 you can see the basic components of a timer. We have discussed a part of them already:

  • TCNT is the timer counter register. It stores the current value of the counter and it is incremented periodically. Depending on the timer type it can have 8 or 16 bits.
  • The prescaler divides the frequency of the clock by 1, 8, 64, 256, 1024.
  • OCR is the Output Compare Register. The timer can be set to count up until it reaches the value stored in OCR. When OCR becomes equal to TCNT an interrupt is issued.

Each timer has his own TCNT, OCR etc. registers. To distinguish between them their names are followed by the timer number (e.g. TCNT0 belongs to timer/counter 0 etc.). Moreover, timers are detailed individually in the datasheet.

Modes of operation

The mode of operation, i.e., the behavior of the Timer/Counter and the Output Compare pins, is defined by the combination of the Waveform Generation mode (WGM02:0) and Compare Output mode (COM0x1:0) bits. The Compare Output mode bits do not affect the counting sequence, while the Waveform Generation mode bits do. The COM0x1:0 bits control whether the PWM output generated should be inverted or not (inverted or non-inverted PWM). For non-PWM modes the COM0x1:0 bits control whether the output should be set, cleared, or toggled at a compare match[1].

The ATmega328P presents four modes of operation:

  • Normal
  • CTC (Clear Timer on Compare match)
  • Fast PWM
  • Phase Correct PWM

The PWM modes will be detailed in Section 2.12. PWM.

The simplest mode of operation is the Normal mode. In this mode the counting direction is always up incrementing), and no counter clear is performed. The counter simply overruns when it passes its maximum value (TOP = 0xFF for 8-bit timers, TOP = 0xFFFF for the 16-bit timer) and then restarts from the bottom (0x00). In normal operation the Timer/Counter Overflow Flag (TOV) will be set in the same timer clock cycle as the TCNT becomes zero[1].

In Clear Timer on Compare or CTC mode, the OCR0A Register is used to manipulate the counter resolution. In CTC mode the counter is cleared to zero when the counter value (TCNT) matches the OCR0A. The OCR0A defines the top value for the counter, hence also its resolution. This mode allows greater control of the compare match output frequency. It also simplifies the operation of counting external events. The counter value (TCNT) increases until a compare match occurs between TCNT and OCR, and then counter (TCNT) is cleared.

TOP value

CTC mode allows us to issue an interrupt when the counter reaches TOP, where the top value is what we put into the OCR register. In addition to this, we know that the normal mode of operation counts until it the register is full, issues an interrupt and then starts over. But how do we choose that value in CTC mode such that it corresponds to a certain period of time? And what do the maximum values in normal mode correspond in terms of time? So far we have discussed the counting properties of this device and in this section we are going to detail the mathematics that allows us to associate time to an integer value.

We have stated in equation (1) that an interval of time is inverse to frequency. We know the target frequency, the microcontroller input frequency and we can vary the prescaler value. In this respect, we can deduce the following:

Target Period of Time = 1 / Target Frequency  (2)
Counting Period of Time = 1 / Timer Clock Frequency  (3)

The meaning of the variables used:

  • The Target Period of Time represents the desired period of time between two interrupts.
  • The Counting Period of Time represents the period between two increments of the TCNT register.
  • Target Frequency represents the frequency at which interrupts should be issued.
  • Timer Clock Frequency represents the frequency at which the TCNT register is incremented.

We also know that the Timer Clock Frequency depends on the Microcontroller frequency (Input Frequency) and the Prescaler value (Prescale):

Timer Clock Frequency = Input Frequency / Prescale  (4)

We can now express the value to be placed in the OCR register for the CTC mode (Target Timer Count):

Target Timer Count = Target Period of Time / Counting Period of Time - 1  (5)

Using equations (2,3,4) equation (5) becomes:

Target Timer Count = (1 / Target Frequency) / (Prescale / Input Frequency) - 1  (6)

Or, rearranged:

Target Timer Count = (Input Frequency / Prescale) / Target Frequency - 1  (7)

Note: All periods of time are expressed in seconds and all frequencies in Hertz. Other measuring units should be transformed accordingly.

There are only two conditions for choosing the right Target Timer Count when varying the Prescale value:

  • The result must fit into the 8-bit or 16-bit OCR register.
  • The result must be an integer. If your value is not an integer do not attempt to truncate the number, you will only lose accuracy. The solution is to choose an other Prescale value.

Pseudocode

In the following instructions consider that x represents the timer number. Thus, TCCRxA represents TCCR0A, TCCR1A or TCCR2A, depending on the timer that you are using.

To initialize a timer:

  1. Select the timer mode of operation (WGM01:0 bits in the TCCRxA register)
  2. Set the prescaler with the appropriate value (as explained in section //TOP value//; CS02:0 bits in the TCCRxB register).
  3. If you have selected the CTC mode of operation, set OCRxA or OCRxB (or both registers, if your application needs them).
  4. Set the Compare Output Mode, if necessary (COMxA1:0 and COMxB1:0 in the TCCRxA register)
      - These bits control the Output Compare pin behaviours. On compare match, the pin can be toggled, cleared, set or ignored (if it is 
disconnected because of the timer mode of operation).
  5. Either:
      a) Monitor the corresponding bit in the TIFRx register (Timer/Counter x Interrupt Flag Register):
          * OCFxA: Output Compare A Match Flag
          * OCFxB: Output Compare B Match Flag
          * TOVx: Timer/Counter x OVerflow Flag
      b) Generate an interrupt

To activate a timer interrupt:

  1. Enable global interrupts: sei();
  2. Activate the chosen interrupt (TIMSKx register)
      a) OCIExA: Output Compare Match A Interrupt Enable
      b) OCIExB: Output Compare Match B Interrupt Enable
      c) TOIEx: Timer/Counter x Overflow Interrupt Enable
  3. Define an interrupt handling routine wchich takes as argument the appropriate interrupt vector (see the description below).
      - Don't forget about the interrupt header: #include <avr/interrupt.h>

Timer interrupt vectors for the ATmega328P:

  - TIMER2_COMPA_vect
  - TIMER2_COMPB_vect
  - TIMER2_OVF_vect
  - TIMER1_CAPT_vect
  - TIMER1_COMPA_vect
  - TIMER1_COMPB_vect
  - TIMER1_OVF_vect
  - TIMER0_COMPA_vect
  - TIMER0_COMPB_vect
  - TIMER0_OVF_vect

where:

  * COMPA, COMPB: Compare Match A / B. There are two Output Compare Units per timer and both of them are compared to the TCNT value.
  * OVF: Overflow. An overflow happens when the TCNT register has reached its maximum value and at the next increment it starts over from 0.
  * CAPT: The 16-bit Timer/Counter 1 also incorporates an Input Capture unit that can capture external events and give them a timestamp 
indicating time of occurrence. The external signal indicating an event, or multiple events, can be applied via the ICP1 pin or alternatively, 
via the analog-comparator unit[1]. 

Common mistakes

  • If you use the CTC mode of operation then you need to compute the value for the OCR register. This value is different depending on the prescaler value chosen. However, you have to keep in mind that there are two restrictions: the value resulted has to fit in OCR (maximum 255 for 8-bit timers and 65535 for 16-bit timers) and it has to be an integer. It is a mistake to compute a value and truncate the floating point so it would fit in the register, this will lead to a loss of accuracy.
  • Remember to first express all the values in seconds and Hertz before attempting to compute the result of equation (7).
  • You should not load the microcontroller with unnecessary computing operations. In this respect, you can compute manually (or with the help of the Windows calculator) the result of equation (7) and insert into OCR the result rather than making the microcontroller do the computation for you.

Bibliography

  1. The datasheet for ATmega328P: http://www.atmel.com/Images/doc8161.pdf
  2. elf.cs.pub.ro/pm

Resources

roboticsisfun/chapter2/ch2_11_timers.txt · Last modified: 2012/11/04 01:24 by silvia.stegaru