COMMON TIMER/COUNTER THEORY
INTRODUCTION:
The AVR has an interesting counting circuit. This circuit has 2 inputs and one output. If you tie it into the Tn pin it will count the pulses on the pin (this is referred to as a counter on the datasheet). If you tie it into the AVRs internal(or external) clock you now have a timer. If you tie the counter to the output you will get an Pulse Width Modulator signal on the OCnx pin.
This chapter talks about the Timer/Counter/PWM circuit in a basic way. More details can be found in each of the following sections.
THEORY OF OPERATION:
Figure 1: Common Timer/Counter with PWM Circuit
When the Control Logic component gets a pulse from the prescaler(more on the Prescaler later) it increments(or decrements) the TCNTn register. The TCNTn register is compared to the OCRn register. When the TCNTn register reaches the same value as the OCRn value or the TOP/BOTTOM value(0xFF for 8bit registers and 0xFFFF for 16bit counters) the Control Logic clears the TCNT register and activates the TOVn bit (Timer Overflow) which stays set until it is reset by the user. Figure 2 shows this in graph form.
Figure 2: Timer/Counter Timing Diagram
Figure 2 is a bit confusing so I will explain it.
First graph (in red) shows the pulses generated by the system clock(clk).
The second graph(in blue) shows us the pulses coming out of the prescaler (clk_tn or clk/8). In our example the prescaler is set to 8 so, it divides the clk(red) by 8. More details on the prescaler in the next section.
The third line shows the TCNTn (basically the count). The TCNTn updates on the falling edge of the pulse coming out of the prescaler. On our first prescaler pulse (in blue) our TCNTn is TOP-1 (or 254). On our second prescaler pulse(in blue) our TCNTn goes to TOP (or 255). Now, on our third prescaler(in blue) pulse the TCNTn register overflows back to the BOTTOM (or 0) because it was at its TOP value on the previous pulse. On our forth prescaler pulse(in blue) the TCNTn register gets incremented again this time to BOTTOM + 1 (or 1).
The forth line shows the TCNTn register again. The only difference is that it shows TCNTn register in a Phase Corrected PWM pattern, which means that it counts up until it hits the TOP and then start to count down until it hits the BOTTOM. I will get into greater details about this in the PWM chapter.
The fifth line (in green) shows us the TOVn (Timer Overflow bit). This bit is set the first time that a timer overflows. Or in other words the first time that the timer goes from its TOP state to its next state (BOTTOM in the Third line or, TOP -1 in the forth line).
The sixth line shows the OCRnx register. This register deals with the PWM. The only thing that it is showing, is that the OCRnx register can only be updated when an TOVn (timer overflow) condition happens. More on the OCRnx register in the PWM section.
Prescaler:
Figure 3: Timer/counter2 Prescaler
The divides the number of input pulses. In other words, the prescaler counts the number of input pulses (from the internal clock or from external sources) and when the number reaches the preset number (0, 8, 32, 64, 128, 256 or 1024) it generates a pulse of its own. This can be seen in Figure 2 (above) which divides the input by 8. This is needed because the AVR only has an 8bit and a 16bit register and the AVR can run as fast as 20Mhz. This means that the larger 16bit timer would pulse every 3ms. But what if we want a 1 second timer? Well we would have to divide the number of incoming pulses by 1024 we could then generate a counter pulse every 3 seconds.
The math is fairly simple:
AND
And don't forget the old
Above I said that an AVR running at its max speed (20Mhz) could only generate a pulse every 0.003 seconds without a prescaler. I go this number by:
Period / Frequency = Time
Time = Period / Frequency
Time = 16bit_register_size / System_clock_speed
Time = 0xFFFF / 20Mhz
Time = 0.00327675 s
Time = 3.27675 ms .... then I rounded for the writeup
Then I said that thanks to the prescaler we could generated up to a 3s timer. I got this by using the max time from above and the max prescaler setting of 1024.
Prescaler_output_time = 0.00327675 * 1024
Prescaler_output_time = 3.355392 s ... Again, I rounded for the writeup
Digging around the datasheet, if found and interesting fact. It is recommended that all external sources are limited to system clock / 2.5 therefore if you are running at the maximum speed of 20Mhz you are only able to reliably measure up to an 8Mhz signal. The Arduino runs at 16Mhz therefore we are limited to 6.4Mhz or less.
Finally, starting the prescaler will start the timer, so I recommend setting the prescaler bits last when setting up your timer in your program.
OTHER RESOURCES:
Covers everything about timers (this chapter and all the other chapters within this section).
As always, the first one is free, and just enough to get you hooked.
Cheers
Q