Arduino Tutorial - Timer

Discover our wide range of Arduinos and accessories!

As an Arduino programmer, you have probably used timers and interrupts without even knowing it's there because all the lower level hardware components are hidden by the Arduino API. Many Arduino functions use timers, for example the timing functions: delay (), millis () and micros (), the PWM functions analogWrite (), tone () and noTone (), even the servo library uses timers and interrupts .

What is a timer?

A timer or counter is a piece of hardware on the Arduino controller. It is like a clock and can be used to measure time events.
The timer can be programmed by some special registers. You can configure the pre-scaler for the timer or the operation mode and many other things.

Many Arduino board are based for example on an Atmel AVR ATmega168 or a m ATmega328 microchip. These chips are pin compatible and differ only in the size of the internal memory. Both have 3 timers (Timer0, Timer1 and Timer2). Timer0 and Timer2 are 8-bit timers, where Timer1 is a 16-bit timer.

The most important difference between 8-bit and 16-bit timers is the timer resolution. 8 bits means 256 values (two to the power of 8), where 16 bits means 65536 values (two to the power of 16), which is a much higher resolution.

The Arduino Mega series is based on the Atmel AVR ATmega1280 or the ATmega2560. They are almost identical to earlier chips, but differ only in memory size. These chips have 6 timers. The 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 depend 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 have been configured to a 1 kHz frequency, and interrupts are generally enabled.

Timer Register

You can change the timer behavior using the timer register. The main timer registers are:

  • TCCRx - Timer / Counter Control Register. The prescaler can be configured here.
  • TCNTx - Timer / counter register. The current timer value is stored here.
  • OCRx - Output Compare Register
  • ICRx - Input Capture Register (only for 16bit timers)
  • TIMSKx - Timer / Counter Interrupt Mask Register. To enable / disable timer interrupts.
  • TIFRx - Timer / Counter Interrupt Flag Register. Indicates a pending timer interrupt.

Using Timer with an Arduino Uno

A timer is used because you can't do anything during the delay () function. But with a timer, you can do anything because when the moment comes, it activates the interrupt.

In this example, TIMER0 is used because it is the easiest timer to configure. First, let's look at the datasheet of the ATmega328P for this.

The prescaler receives a pulse of one clock cycle and then forwards it to the control logic, therefore the control logic increments the TCNTn register by 1.

Now we can compare the value of TCNTn with a certain value. When the TCNTn register reaches this value, you know that a certain time has elapsed.

This method is called CTC mode for "Clear Timer on Compare". The value TCNTn register is compared with the OCRn register, when a comparison match occurs, the TOVn generates an interrupt.

Another important thing is the prescaler, which allows you to create different areas of the clock, in fact 16MHz is too much, but thanks to the prescaler you can create some submultiples of it. This depends on the configuration of the TCCR0B register.

Another important thing is to determine the value of the OCRn register to count a certain time, for this you need a bit of math.

For better understanding you should have a look at the code below. There, an interrupt request is activated every 0.001 seconds.

Arduino Internal Timer Code

/* This program turns on and off a LED on pin 13 each 1 second using an internal timer */ int timer=0; bool state=0; void setup() { pinMode(13,OUTPUT); TCCR0A=(1<<wgm01); set="" the="" ctc="" mode="" ="" ocr0a="0xF9;" value="" for="" orc0a="" 1ms="" ="" timsk0|="(1<<OCIE0A);" interrupt="" request ="" sei();="" enable="" interrupt ="" tccr0b|="(1<<CS01);" prescale="" 1="" 64="" clock ="" loop()="" { ="" in="" this="" way="" you="" can="" count="" second="" because="" nterrupt="" request="" is="" each="" 1ms ="" if(timer="">=1000){ state=!state; timer=0; } digitalWrite(13,state); } ISR(TIMER0_COMPA_vect){ //This is the interrupt request timer++; }</wgm01);>

Fritzing Schematics