When doing microcontroller-based development, you will certainly
encounter a counter/timer peripheral. This article aims to explain the
concepts behind understanding and configuring a counter/timer using the
same techniques you probably used in high school science classes for
unit conversions and stoichiometry: dimensional analysis.
As a review, let's say you need to convert two (2) miles to meters.
You recall that a "5K" race is approximately 3.1 miles, so you can use
that as a conversion factor. You also know that there are 1000 meters
in a kilometer.
Even though you do not know the conversion factor to go directly
from miles to meters, you are still able to do the conversion because
you can eliminate or "cancel out" units on intermediate conversions
from miles to kilometers to meters:
* The "mile" in the denominator of 5 km/3.1 miles cancels out the
"miles" in 2 miles.
* The "km" in the denominator of 1000 meters/km cancels out the "km" in
5 km/3.1 mile.
* And, finally, you are left with the only units remaining being
meters, which are the units you wanted.
This article does not talk about a specific counter/timer
peripheral, but the concepts covered will be relevant to any you will
encounter. Some counter/timer peripherals may not have all the features
mentioned in this article, or may have even more features.
Regardless of the features provided by your hardware, if you keep
track of how various settings affect the units, you will be able to
understand any counter/timer peripheral.
These same principles can be applied to other hardware peripherals
as well, especially the "baud rate generator" of a UART or clock rate
of a serial peripheral.
Getting down to timer basics
First of all, you may be wondering, "Why is that slash in the middle of
'counter/timer'?" A counter/timer peripheral is a hardware device that
counts events such as toggles of an input pin. That explains the
"counter" part. What about "timer"? A "timer" is just a counter that
uses a periodic clock signal as its input: it just counts time.
The rest of this article will refer to a counter/timer peripheral as
just a "timer," but bear in mind that many people will use the term
"counter" and others will use the term "timer" to refer to the same
type of peripheral. Some developers and chip manufacturers will even
mention "timer in event counter mode" to indicate the peripheral is
counting an event other than a clock signal.
A timer has an input source, which is the pin monitored by the
hardware before updating its internal counter. Whenever that input
source signal goes from low-to-high, or vice versa, the timer will
update its internal count value. Some timers count up from zero, others
count down towards zero, and some have configurable directions.
Regardless of which direction your device counts, the principle of
operation is the same: each time that input pin changes in the
specified way, the device's internal count either increments or
decrements.
Let's say you've configured your timer's input source to be your
MCU's main clock which is running at 8 MHz. That means that the
internal counter value will change, or tick, with a frequency of 8 MHz
= 8 x 106 cycles/sec or 125 ns/cycle. That is, one (1) tick
every 125 ns.
Prescaling
When looking at the datasheet's description for your timer, you will
likely notice a register for setting the divider or prescaler. That
setting allows you to slow down the ticking. If you choose a prescaler
value of 2, then for every two changes of the input source the timer
will tick only once.
If you choose a prescaler of 16, the input source would change 16
times between each tick. Think "16 MCU clock cycles per timer tick."
Given the same 8 MHz MCU clock source as before, and a prescaler of 16,
to calculate the number of ticks in a second, it is simply a
multiplication:
Notice that the units work out to give us ticks/sec—the MCU clock
cycles units "cancel out," and we are left with ticks/sec. To calculate
the amount of time that has elapsed between each tick of the hardware
timer, just calculate the multiplicative inverse/reciprocal so that the
units become sec/tick:
Time-outs
If your timer peripheral had an internal counter with infinite range
and your peripheral gave you read access to the counter, you could
measure time between two software events by reading the counter value
at the first event, then read the value again at the second event; the
difference is the elapsed time.
However, on real devices, the internal counter has a finite range
and will eventually overflow if a tick increments the value or
underflow if a tick decrements the value.
In this article, I will call an overflow or underflow condition a
time-out. On a time-out, the peripheral will set a flag and may trigger
an interrupt. If you had an 8 bit timer, it would time-out after 28
= 256 ticks. How long before the 8 bit timer times-out with 2
microseconds between ticks?

Most timer peripherals can operate in a repeat mode where, after a
time-out, they reinitialize their internal counter and start counting
again. By checking the flag that is set by the time-out or enabling the
interrupt, you can keep track of time.
Reading the time-out flag or the execution of the corresponding
interrupt service routine (ISR) often clears the time-out flag
automatically; some hardware may require an explicit "clear" of the
time-out flag.
In fact, that is how systems generally keep track of time: a
hardware timer times out periodically, say every millisecond, and a
current_time counter variable in the program or operating system is
updated. (Note that additional care is needed to ensure that the
counter variable does not unexpectedly overflow.)