Advanced Arduino: direct use of ATmega counter/timers

What are the counter/timers

The Arduino platform consists of a set of software libraries that run on a group of micro-controller chips. Currently the supported micro-controllers are the AVR ATmega168, ATmega328, and the more featureful ATmega1280 and ATmega2560 used in the Arduino Mega. Also smaller chips like the ATtiny are useable if you are prepared to do some more homework.

Currently the Arduino platform uses the ATmega series but the software is not strongly tied to any one architecture (in principle).

These notes are, however, firmly tied to the ATmega architecture and the ATmega168 and ATmega328 chips of the standard Arduinos. The ATmega1280 and 2560 are very similar however (but with more counter/timers).

Where to find things out

All things Arduino can be found at or from the Arduino wesbite. Google naturally is very useful for locating more resources. The chip datasheets can be located in numerous places but Atmel's website has them at their ATmega328p doc page.

Existing use/support of counter/timers in Arduino libraries

The standard Arduino has 3 timers, timer0 is 8 bit and used for the millis() and micros() functions. Timer1 is 16 bit and not used by default, timer2 is another 8 bit timer like timer0 but not used by default.

timer bits channel Arduino pin Mega pin
timer0 8 A 6 13
timer0 8 B 5 4
timer1 16 A 9 11
timer1 16 B 10 12
timer2 8 A 11 10
timer2 8 B 3 9
timer3 16 A - 5
timer3 16 B - 2
timer3 16 C - 3
timer4 16 A - 6
timer4 16 B - 7
timer4 16 C - 8
timer5 16 A - 44
timer5 16 B - 45
timer5 16 C - 46

At restart the Arduino bootloader sets up the timers ready for analogWrite() PWM use. The timer/counters are set to phase-correct 8-bit PWM mode and with clock prescaled to system clock divided by 64. However timer0 is set to fast PWM mode for use with the millis()/micros() code.

For standard Arduinos the system clock is 16MHz so that the timers are clocking at 250kHz by default. Phase correct 8-bit PWM mode takes 510 clocks to cycle and fast 8-bit PWM mode takes 256. This means a frequency of 490Hz for pins 5 and 6 and 977Hz for pins 3, 9, 10, 11 when used with analogWrite(). It is possible to change the clock prescaling to change these default PWM frequencies.

ATmega counter-timer basics

The counter/timer hardware modules are very flexible and consist of a set of registers to control the behaviour as well as the counter/timer register itself. 16 bit timers have mainly 16-bit registers (although the control registers are 2 separate 8-bit ones in all timers).

In the following description I shall use timer1's register names, but the naming is systematic and replacing the '1' by another number you get the corresponding names. TCCR1A and TCCR1B are the two 8-bit control registers. These set up the clock prescale ratio, set the mode for the counter/timer and set the output control for the PWM pins. TCNT1 is the 16 bit (for timer1) counter value itself. At the assembly language level this register has to be written or read as two 8-bit half-registers and in a certain order. The GCC AVR compiler used by the Arduino software automatically generates the two accesses as if this was a single 16 bit transfer. However if you have an interrupt handler that also accesses 16 bit registers in the same timer you must protect accesses by disabling interrupts across the access.

Each timer has 2 or 3 channels which control a dedicated pin if the relevant output mode is set and that pin is enabled as an output. The OCR1A and OCR1B are the 16 bit Output Compare Registers that apply to the two channels (A and B) that timer1 has. The Mega has timers 3 4 and 5 that each have 3 channels, A, B and C. The same considerations about 16 bit transfers as for the TCNT1 register of course.

The Input Capture Register ICR1 is a 16 bit register used to record the value of TCNT1 when an external event happens - typically a change on the ICP1 pin (Arduino pin 8). Only 16 bit timers have input capture.

The basic operation of the unit, common to most modes is for the counter register TCNT1 to count up and/or down between values BOTTOM (which is zero) and TOP. In some modes TOP is provided by a register such as OCR1A or ICR1, in other modes it is fixed at 0xFF or 0x1FF or 0x3FF or 0xFFFF (MAX). Many modes compare the OCR1A and OCR1B values to the TCNT1 at each clock and may change the output pins for those channels. In phase-correct PWM mode the counter reverses direction when getting to BOTTOM or TOP thus ramping both up and down. In other modes the counter just counts up and resets to BOTTOM (usually zero) upon reaching TOP.

There are interrupt handlers for several events associated with a timer, namely overflow, compare matching on A or B, and input capture. The names for the interrupt vectors are TIMER1_CAPT_vect, TIMER1_COMPA_vect, TIMER1_COMPB_vect, TIMER1_OVF_vect. There is no CAPT vector for timers 0 and 2 since they are 8-bit.

Control register set-up

The TCCR1A and TCCR1B registers can be programmed thus:

void timer1_setup (byte mode, int prescale, byte outmode_A, byte outmode_B, byte capture_mode)
{
  // enforce field widths for sanity
  mode &= 15 ;
  outmode_A &= 3 ;
  outmode_B &= 3 ;
  capture_mode &= 3 ;

  byte clock_mode = 0 ; // 0 means no clocking - the counter is frozen.
  switch (prescale)
  {
    case 1: clock_mode = 1 ; break ;
    case 8: clock_mode = 2 ; break ;
    case 64: clock_mode = 3 ; break ;
    case 256: clock_mode = 4 ; break ;
    case 1024: clock_mode = 5 ; break ;
    default:
      if (prescale < 0)
        clock_mode = 7 ; // external clock
  }
  TCCR1A = (outmode_A << 6) | (outmode_B << 4) | (mode & 3) ;
  TCCR1B = (capture_mode << 6) | ((mode & 0xC) << 1) | clock_mode ;
}
Note that timer2 has different prescaler codes from all the other timers - consult the datasheet.

The output modes are 2-bit values affecting the pin relevant to that channel, with following meanings
codemeaning
00
01
10
11

The 16 modes are summarized in this table.
code Mode TOP Update of OCR1x TOV1 Flag Set
0 Normal 0xFFFF Immediate MAX
1 PWM, Phase Correct, 8-bit 0x00FF TOP BOTTOM
2 PWM, Phase Correct, 9-bit 0x01FF TOP BOTTOM
3 PWM, Phase Correct, 10-bit 0x03FF TOP BOTTOM
4 CTC OCR1A Immediate MAX
5 Fast PWM, 8-bit 0x00FF BOTTOM TOP
6 Fast PWM, 9-bit 0x01FF BOTTOM TOP
7 Fast PWM, 10-bit 0x03FF BOTTOM TOP
8 PWM, Phase and Frequency Correct ICR1 BOTTOM BOTTOM
9 PWM, Phase and Frequency Correct OCR1A BOTTOM BOTTOM
10 PWM, Phase Correct ICR1 TOP BOTTOM
11 PWM, Phase Correct OCR1A TOP BOTTOM
12 CTC ICR1 Immediate MAX
13 (Reserved) - - -
14 Fast PWM ICR1 BOTTOM TOP
15 Fast PWM OCR1A BOTTOM TOP
Note that the TOV1 flag is set when the counter overflows, normally when it clocks round to zero or when it reaches MAX or TOP depending on the mode. This, if enabled, triggers the TIMER1_OVF_vect interrupt.

Pulse Width Modulation - PWM

There seem to be a bewildering variety of PWM modes, but the basic varieties are fast, phase-correct and frequency-and-phase-correct. Fast simply counts up till TOP and resets to zero (BOTTOM). The others count up to TOP and then count down to BOTTOM and then count up again, etc. This keeps the waveform symmetric as the duty-cycle varies, but has nearly twice the period of the equivalent fast more. Frequency-correct really means frequency-settable in that the value of TOP is not constrained to a power of two but is controlled by either ICR1 or OCR1A in particular the value of TOP is carefully changed only at a safe point when TCNT1 == BOTTOM. Several of the modes set the counter to being effectively 8, 9 or 10 bits. The default arrangement on the Arduino is 8-bit phase-correct (or on timer0, 8-bit fast).

Counting

In normal and CTC modes the counter is simply counting and not controlling the PWM output channels - in CTC mode TOP can be controlled. To truly count the clock configuration should be set to the external clock options uses pin T1 which is Arduino pin 5. In these modes the overflow interrupt only happens if the counter reaches MAX (0xFFFF) - if this is handled then more than 16 bits of counting is possible with the aid of software. You can measure frequency, say, by using timer1 to count input pulses this way and sample the result in an overflow interrupt on a different timer (which is used as a timer not a counter).

Timing

Any mode can be used for timing if the clock source is set appropriately (prescaled system clock). Timing is simply counting system clocks. Accurate timing requires the system clock is crystal-controlled. The new Arduino Uno doesn't have a crystal clock and is not suitable for more than 0.2% accuracy. Most crystal-derived clocks give better than 0.01% accuracy. For times to microsecond accuracy a prescale of 1 or 8 is needed and an interrupt handler should be used since polling is likely too slow and other interrupts generate jitter.

Timed interrupts