Main Content

Previously, we looked at using registers directly in Arduino and setting up external interrupts. This time, we configure a timer interrupt to toggle an LED every 0.5 seconds. That’s right; we’re going to redo blinky the hard way.

The ATmega328P has three timers that continually increment. Note that Arduino uses them for various functions, which means you probably don’t want to use those functions if you plan to mess with the timers. On the UNO and RedBoard, you will find:

- Timer0 - 8 bits (0 - 255) - Compare Match, Overflow - delay(), millis(), micros(), analogWrite() pins 5, 6
- Timer1 - 16 bits (0 - 65,535) - Compare Match, Overflow - Input Capture - Servo functions, analogWrite() pins 9, 10
- Timer2 - 8 bits (0 - 255) - Compare Match, Overflow - tone(), analogWrite() pins 3, 11

Each of these timers can be configured for one or more interrupts:

- Compare Match — When the timer value reaches a specific value (stored in the corresponding output compare register), an interrupt will be generated. This can be useful for creating pulse width modulation (PWM) signals on pins or sampling a sensor at specific intervals.
- Overflow — When the timer rolls over from its max value (e.g., 65,535) to 0, an interrupt is generated. Overflow interrupts are also used for PWM signals and running pieces of code at precise intervals.
- Input Capture — When a specific pin changes value (e.g., ICP1), the current timer value is stored in another register (ICR1) that can be retrieved later to see the exact time that event occurred. This type of interrupt is good for measuring the time between pulses.
- To help make timing longer events easier (especially when some of the timers can only count up to 255), a prescaler can be used. A prescaler, in effect, divides the system clock to make something operate more slowly. For example, here is Timer1 counting up to 15 with no prescaler. You can see how Timer1 increments on every rising edge of the system clock.”

Link to article