What do counter and time delays mean?

8051 microcontroller

Until now, time delays have been created using time loops. However, many applications require exact time delays or time spans.
With time loops it is practically impossible to program exact time delays. In addition, the microcontroller cannot perform any other tasks when processing a loop.

Timers are used to relieve the microcontroller and to meet exact time conditions.
A timer counts clock pulses and triggers an interrupt request in the event of an overflow.

The timer can be used both as a timer and as an event counter.

Overview of the timer addresses

(e.g. timer 0 to 000B and timer 1 to 001B)

Timer 0 and Timer 1 each consist of two 8-bit counters.
Depending on the desired mode, they can be used as 8-bit or 16-bit counters.

Counting register

The 8-bit counter registers are the special function registers TL0 (Timer Low 0) and TH0 (Timer High 0) for Timer 0 as TL1 (Timer Low 1) and TH1 (Timer High 1) for Timer 1.

If both registers are connected in series, a 16-bit counter results (216 = 65636 counting steps)

The two Counter registers TL0 and TH0 can be set to certain initial values ​​(00 00 to FF FF).
In this example, the initial value is on 0FAF (4015) set. From these values ​​they count upwards after the counter has started FFFF (65636).

If the counter overflows (from FF FF with the next bar = Overflow, that will Overflow flag TF0 set.

Overflow flag

The overflow flag can be queried by the program or trigger an interrupt. If the flag is queried by the program, it must also be deleted again by the program.

After the overflow, the counter can be reset to an initial value. If no initial value is set, the counter starts at 0000.

Use of timer 0 as a timer

If a timer is used as a timer, the counters are incremented by the system clock. This adds the period duration of the system clock via the counter.
Depending on the initial value of the counter, there is a certain time delay before the overflow occurs. However, this time delay is no longer dependent on the current program.

The timer, which is clocked by the system clock, is to be regarded as an independent hardware module.
The time delay and thus the system clock is determined by the respective crystal frequency.

With an oscillator frequency of 12MHz the result is a internal system clock of 1MHz.
1MHz corresponds to a system time of 1us per cycle.


A system cycle of 50ms is to be generated. The timer flag should be set after 50ms.
a.) With which values ​​does the timer (in 16-bit counter mode) have to be preloaded?
b.) What has to be changed in order to generate a cycle of 1s?

A complete pass corresponds to 65636 states (65636 us).
50 ms = 50000 us -> 65636 - 50000 = 15536

a.) To generate a time of 50ms, the timer must be preloaded to the decimal number 15536.
This corresponds to the HEX number 3CB0!

TH0 is therefore precharged with 3C and TL0 with B0:

Assembly code

MOV TL0, # B0h; Pre-loading of timer 0 (low byte) with B0
MOV TH0, # 3Ch; Pre-loading of timer 0 (high byte) with 3C

b.) Since the timer can generate a maximum of 65.636ms per run, e.g. an additional register must be incremented by 1 with each run, as long as up to 20 runs (50ms x 20 = 1s) are achieved.

If the counter overflows at 65636, its overflow flag (TF0) is set to 1.

There are two options here:

  1. The flag triggers an interrupt. The running program is interrupted and an interrupt service routine is executed.
  2. The flag is queried by the program. If it is set, a corresponding action is carried out and the flag is reset.

Set the time and start the timer 0

  1. Stop the clock signal
    CLR TR0
  2. Preload timer low byte with AF
    MOV TL0, # 0AFh
  3. Preload timer high byte with 0F
    MOV TH0, # 0Fh
  4. Reset overflow flag
    CLR TF0
  5. Start clock signal
    SETB TR0

Setting the timer function with TMOD

The timer mode register TMOD is an 8-bit register.
The upper 4 bits are for the Timer 1 and the lower 4 bits for the Timer 0 used.

Setting the working mode M0 and M1: (For the two most common working modes)

Setting the 16-bit counter: M0 = 1 and M1 = 0
Both 8-bit counting registers are in series here and form 216 (65536) stacks.

Setting the 8-bit autoreload counter: M0 = 0 and M1 = 1
In the event of an overflow, the value is copied from the high byte (TH0 or TH1) to the low byte.
The high byte remains unchanged in this case.

Overview of all operating modes

Block diagram of the timer in mode 1

With C / T you can choose between the event counter (for external counter) and timer operation.
C / T = 0 -> function as a timer
C / T = 1 -> function as a counter

With GATE choose between the internal or external release of the counter / timer.
GATE = 0 -> internal release via TR0 or TR1
GATE = 1 -> external release takes place via port pins P3.2 or P3.3 and internal release via TR0 or TR1.

Block diagram of the timer in mode 2

Overview of the addresses and functions of the Timer Control Register TCON

Description in assembler
  1. Initialization of the timer

    MOV TMOD, # 01h (Timer 0 as 16-bit counter M0 = 1)

    01h = 00000001 binary

    MOV TMOD, # 10h (Timer 1 as 16-bit counter M0 = 1)

    10h = 00010000 binary

  2. Pre-loading the timer

    MOV TL0, # B0h; Pre-loading of timer 0 (low byte) with B0
    MOV TH0, # 3Ch; Pre-loading of timer 0 (high byte) with 3C

  3. Starting and stopping the timer

    SETB TR0 (Timer0 start: set run bit)

    SETB TR1 (Timer1 start: set run bit)

    CLR TR0 (Stop timer 0)

    CLR TR1 (Stop timer 1)

  4. Reading out the timer value

    MOV R7, TH0 (Load timer value high byte from timer 0 into register 7)

    MOV R6, TL0 (Load timer value low byte from timer 0 into register 6)