Skip to content

uPesy now ships to the entire European Union

Contents Menu Expand Light mode Dark mode Auto light/dark mode

How do the timers of a microcontroller work?

You have probably already heard of**a timer,** but do you really know what it is used for and how it works? In this article, we will discover the different use cases of**a timer on a microcontroller** as well as its theoretical functioning. This knowledge will allow you to use effectively timers in your Arduino, MicroPython programs. Let’s start by defining what a timer is 😊

The timer, an electronic counter

A timer is an electronic counter capable of counting the time that elapses in a very precise way. In fact, it is a register inside a microcontroller that increments each time it receives a pulse from a clock signal generated internally by the microcontroller. We will use timers rather than using the microprocessor to count, which is what the Arduino function delay() function, which is blocking.

The hardware timers are independent blocks of the CPU. They take care of counting continuously while the program can execute other functions.

Note

The Arduino functions millis() and micros() functions use a timer to work.

Timers offer additional functionality, for example triggering alarms when a certain threshold is reached. For example, tasks can be executed periodically with interrupts generated by a timer.

What is the purpose of a timer on a microcontroller: use cases

The timer can be used for its basic function: to measure time precisely. It can be interesting to know the execution time of a program or to know the time since the launch of the program.

In practice, we often use a particular feature of timers: generating interrupts when the counter reaches a certain threshold value. Here is what you can do by taking advantage of this feature:

  • Make scheduled tasks: a timer can be configured to trigger an interruption at regular intervals, which can be used to update displays, monitor sensor inputs ..

  • Generate PWM signals: a timer can be used to generate PWM signals to control the speed of a motor, the brightness of an LED, etc.

  • Event synchronization: a timer can be used to synchronize events internally or with external devices.

  • Create timeouts: maximum waiting time

Note

Timers are used in Arduino functions without being necessarily aware of it, in basic functions (milices() and micros() ), for PWM and in libraries (Servo )

I’ll tell you a little more about the inner workings of a timer. It’s important to understand how it works under the hood to configure it correctly later in your programs 😊.

The internal workings of a timer

Timers cannot count indefinitely. They are limited by their resolution quantified in bits. For example, the Arduino has 2 timers of 8bits and 1 of 16bits. This means that 2 timers can count between 0 and 255, and the other between 0 and 65 535. On an ESP32 board, there are 4 timers of 64bits, which can count between 0 and 18,446,744,073,709,552,000 (There’s plenty to do 😉.)

If the timer exceeds its maximum value, there is what is called an overflow. In this case, the counter is usually reset to zero autoreload and an internal alarm is generated to warn the microprocessor.

Operation of a timer in a microcontroller

The time that elapses between each “tick” of the timer obviously depends on the frequency of the clock. At each rising edge of the clock, the counter is incremented. With a frequency of the order of several tens of MHz, the time is very short and the counter will very quickly overflow.

Fortunately, it is possible to reduce this frequency thanks to internal components of the microcontroller, called dividers or prescalers in English. A prescaler allows to divide the frequency of the clock and to increment more slowly. For example, with a prescaler of 4, the counter will count 4 times slower than the clock signal.

Chronogram of a timer counting up to 5

Note

A timer is configured with its period via the value of the prescaler and the``autoreload`` .

Calculate the value of the prescaler and the``autoreload`` from the desired timer period

The period of the timer is the time that elapses between 2 overflows of the counter. To calculate it, we can use the following formula:

\[T_{timer}=T_{horloge}\times prescaler \times (autoreload+1)\]

Note

The counter counts from 0 to autoreload inclusive, i.e \((autoreload+1)\) values.

In general, we know the period of the timer that we would like to have: we rather look for the values of the parameters. There are several pairs of possible solutions for a given period. Indeed, one can either have a low prescaler (high counting frequency) with a high overflow or vice versa. We cannot find the 2 values separately. One must choose one, to determine the other.

\[autoreload = \frac{T_{timer}}{T_{horloge}\times prescaler}-1\]

Let’s take a clock of 80 MHz, we want to have a timer period of 1 second. By choosing a prescaler of 1, the overflow value is :

\[autoreload = \frac{T_{timer}}{T_{horloge}\times prescaler}-1 = \frac{1}{\frac{1}{80.10^{6}}}-1 = 80.10^{6}-1\]

The autoreload value must be storable in the timer register**** in the timer register, i.e. have a value less than \(2^{résolution\space timers}\) bits. For the ESP32 this is ok, but not for the Arduino timers. It would be necessary to take a more important value of prescaler.

Note

Sometimes it is not possible to find exactly the right values of the parameters. Therefore, it will be necessary to make approximations. We can minimize this effect, by taking the smallest possible prescaler.

If we want to obtain a value on 16bits for a timer of the Arduino, we can take a prescaler of 8000 and an autoreload at 9999 :

\[autoreload = \frac{T_{timer}}{T_{horloge}\times prescaler}-1 = \frac{1}{\frac{8000}{80.10^{6}}}-1 = 10000-1 = 9999\]

Of course other prescaler values are possible! The prescaler value is usually chosen arbitrarily, as large as possible, and then the threshold value is deduced.

In practice, we try to take a value which simplifies the calculations: for example a prescaler of 80 for the ESP32 permanent to configure the period of the timer to the nearest microsecond (the frequency of the clock is 80 MHz).

\[autoreload = \frac{T_{timer}}{T_{horloge}\times prescaler}-1 = \frac{T_{timer}}{\frac{80}{80.10^{6}}}-1 = T_{timer}\times10^{6}-1\]

Easier not 😊?

\[autoreload = T_{timer}\times10^{6}-1\]

In addition, on the ESP32, the subtraction is hidden in the function code, so we can simplify the calculation with a prescaler of 80 by :

\[autoreload = T_{timer}\times10^{6}\]

We use cookies to make your visit to the site as pleasant as possible. Privacy Policy