Skip to main content

Command Palette

Search for a command to run...

How does a microcontroller counter work?

Published
4 min read
How does a microcontroller counter work?

A “microcontroller counter” is usually just a timer/counter peripheral inside the MCU that automatically counts clock pulses or external events for you – so you don’t have to do it in software loops.

Let’s break it down in plain language.


1. The basic idea

Inside the microcontroller there is a small hardware block:

  • A clock input (can be an internal clock or an external pin)

  • A prescaler (can divide the clock: /2, /8, /64, …)

  • A counter register (a number that increments or decrements)

  • Optional compare / auto-reload registers

  • Optional interrupts when certain events happen

Every time a tick comes in:

The counter register = counter register + 1
(or −1 if it counts down)

When it reaches its maximum value (e.g. 255 for 8-bit, 65535 for 16-bit), it overflows and starts again at 0.


2. Timer mode vs. Counter mode

Most MCUs use the same peripheral both as a timer and as a counter:

Timer mode (time-based)

  • Clock source: internal clock (e.g. CPU clock or a derived clock)

  • Use: measure time, create delays, generate periodic interrupts.

Example:
If the clock is 1 MHz and the prescaler is 1000:

  • Timer tick = 1 MHz / 1000 = 1000 Hz → 1 ms per increment

  • Every 1 ms the counter increases by 1.

  • When it reaches a certain value (e.g. 1000), you can trigger an interrupt → 1 second passed.

Counter mode (event-based)

  • Clock source: external signals (e.g. pulses on a pin)

  • Use: count things that happen in the real world:

    • Motor encoder pulses

    • Button presses

    • Frequency of a signal

  • Every pulse on the input pin makes the counter increment.

So the same hardware can either:

  • “Tick” with time (timer), or

  • “Tick” when events happen (counter).


3. Key building blocks inside a timer/counter

1) Prescaler

  • Divides the input clock so the counter doesn’t increment too fast.

  • Example: Input clock 16 MHz, prescaler = 16000 → counter sees 1 kHz (= every 1 ms).

2) Counter register (CNT)

  • Holds the current count (e.g. from 0 to 65535).

  • You can read it in software (to see the count).

  • You can write it (to reset or set a starting value).

3) Auto-reload / period register (ARR)

  • Defines when the counter should wrap or trigger an event.

  • Example: ARR = 999 → counter counts 0…999 then rolls over.

4) Compare register (CCR)

  • Lets you trigger an action when CNT == CCR.

  • Used for:

    • Generating PWM

    • Creating precise time points (e.g., toggle a pin at a specific count).

5) Interrupts

  • You can enable an interrupt on:

    • Overflow (update event)

    • Compare match

  • The CPU can then run an ISR (interrupt service routine) whenever that event happens.


4. What can you do with a microcontroller counter?

A lot:

  1. Measure time intervals

    • Start counter at 0

    • Wait for an event (e.g. input pulse)

    • Read CNT; the value tells you how much time passed.

  2. Generate periodic events

    • Configure ARR so overflow happens every 1 ms/10 ms/etc.

    • On each overflow interrupt, do something (update a variable, run control loop).

  3. Count external events

    • Connect a sensor/output to the counter input pin.

    • Configure timer in external clock mode.

    • CNT now equals the number of pulses.

  4. Measure frequency
    Two common methods:

    • Count how many pulses arrive on an input in a fixed time window.

    • Or measure the time between two pulses using the timer.

  5. Generate PWM signals

    • Counter runs from 0 to ARR (period).

    • CCR defines duty cycle:

      • Output pin is high while CNT < CCR, and low otherwise.

5. A tiny pseudo-code example (generic)

Imagine a 16-bit timer, internal clock at 1 MHz, prescaler = 1000:

// Pseudo-code, not tied to a specific MCU
TIMER.PRESCALER = 1000 - 1;   // 1 MHz / 1000 = 1 kHz -> 1 ms per tick
TIMER.ARR       = 999;        // Overflow every 1000 ticks = 1 second
TIMER.CNT       = 0;

TIMER.ENABLE_INTERRUPT_ON_OVERFLOW();
TIMER.START();

Interrupt handler:

void TIMER_IRQHandler(void) {
    if (TIMER.OVERFLOW_FLAG) {
        TIMER.CLEAR_OVERFLOW_FLAG();
        seconds++;  // we now have a 1-second software counter
    }
}

Here the hardware counter gives you a reliable 1-second tick without busy-loops.


6. In one sentence

A microcontroller counter is just a little hardware machine that adds 1 on every clock/event, and lets you react (via registers or interrupts) when certain counts or overflows occur — you use it to measure time, count pulses, and generate precise timings without wasting CPU cycles.

More from this blog

A

Ampheo Electronic Blog-Chip and component knowledge sharing

181 posts

Original and Genuine Electronic Components Distributor