Lecture: 10
Objective: Convert between real time and timer counts and prescalers.
Handout: timer math
timer math solutions

Timer prescaler

The PIC has 7 total timers that all operate on the same principles as timer 0. The "even" timers, TMR2, TMR4, TMR6 are 8-bits wide, meaning that they count-up from 0 to 255 and then roll-over. All the timers have different prescalers which we will learn more about in this lecture.
Timer Width Prescaler Associate module
TMR0 8 or 16-bit 1:1 to 1:256  
TMR1 16-bit 1:1, 1:4, 1:8, 1:16 Capture Compare
TMR2 8-bit 1:1, 1:4, 1:16 PWM
TMR3 16-bit 1:1, 1:4, 1:8, 1:16 Capture Compare
TMR4 8-bit 1:1, 1:4, 1:16 PWM
TMR5 16-bit 1:1, 1:4, 1:8, 1:16 Capture Compare
TMR6 8-bit 1:1, 1:4, 1:16 PWM
In the previous lecture we noted that counting from 0 to 216 the PIC's 16-bit counter took 4.096 ms. With this timer configuration there is no other way to use the timer, by itself, to form longer delays. In order to generate longer delays we would either need to slow down the frequency of the main oscillator Fosc or slow down the counting rate of the clock. The PIC, like many other microcontrollers, has a build-in mechanism to slow down the count rate of timer; prescalers.

Prescaler

A prescaler is a piece of logic that sits between the bus clock and the timer clock.

The timer subsystem, adapted from Figure 11-1 on page 155 of the PIC18(L)F2X/4XK22 Data Sheet.

The prescaler accumulates a prescribed number of bus clocks before issuing a clock tick to the timer. In order to use the prescaler, the prescaler assignment bit in the T0CON must be cleared. In other words, if you want to use a prescaler to slow down the counting rate if TMR0, then the following line of code or its equivlent must appear in your code. T0CONbits.PSA=0;

The value of the prescaler is contained inside the Timer 0 Control register T0CON in your code. Three bits in this register, T0PS2, T0PS1, T0PS0, collectively referred to as PR, control which prescaler is selected. The following table taken from page 154 of the PIC18(L)F2X/4XK22 Data Sheet describes the relationship between the prescaler bits and the prescaler applied to the bus clock before it's sent to the counter.
T0PS T0PS2 T0PS1 T0PS0 Timer clock Max period
0b000 0 0 0 1:2 8.19ms
0b001 0 0 1 1:4 16.4ms
0b010 0 1 0 1:8 32.8ms
0b011 0 1 1 1:16 65.5ms
0b100 1 0 0 1:32 131ms
0b101 1 0 1 1:64 262ms
0b110 1 1 0 1:128 524ms
0b111 1 1 1 1:256 1,049ms
Aside Let's take a moment to look at three different ways that we can assign the prescaler value to say 1:16. The first form assigns each individual bit, requiring three lines of code. The second form shows how you can collect all three prescaler configuration bits together and assign them at once. This results in a single line of code, note that the expression "0b" in front of the three bit value indicates to the compiler that this is a binary number. The third form takes the second idea one step further and assigns all 8 bits of the T0CON register at once. Note that the expression "bits.FIELD" is removed from "T0CON" since we are talking about the entire register. This third form requires you to know the order and The thirs it is possible to write mulitple bits of the T0CON register at once by dropping the "bits.FIELD" from T0CON and using a line of code similar to T0CON = 0b01010101;. This requires that you know the identity and values for the bit fields in the T0CON register. You would need to look at page 154 of the PIC18(L)F2X/4XK22 Data Sheet to get this information.

To put this discussion in concrete terms, if you make the assignment T0CONbits.T0PS = 0b011; in your code, then the 16-bit timer counter will count up once every 16 Fosc/4 cycles. In other words (see the work below) the counter will increment once every microsecond.

     1 second      10^6 us    16 clk    1 us
    ------------ * -------- * ------- = -----
    16*10^6 clks   1 second   1 count   count
I will sometimes use the expression 1:16 to describe when Fosc is being divided by 16. I find it easy to visualize this by thinking of the ' : ' as a ratio symbol that tells me how many Fosc/4 clock cycles it takes to increment the timer.

Time ranges

To see how a prescaler affects the upper-bound of the timer, let's revisit the following code-snippet from the last lecture.
	T0CONbits.PSA = 0;	// Turn on prescaler
	T0CONbits.T0PS = 0b011;	// configure 1:16 prescaler
	T0CONbits.TMR0ON = 1;	// Turn on timer 0
	INTCONbits.T0IF = 0;	// Clear roll-over flag
	while(INTCONbits.T0IF == 0);	// Wait for roll-over flag to be set by counter
Your question is to calculate how long (in milliseconds) the while(INTCONbits.T0IF == 0); statement takes to execute, assuming that the counter starts at 0. In other words, I am asking how long it takes for the counter to roll-over. You will need to use dimensional analysis to prove that your conversion is correct. Like in the previous solutions, I would advise you to start the problem with Fosc/4, move through the prescaler, and then onto the counter.
     1 second      1000 ms    16 clk    2^16 counts 
    ------------ * -------- * ------- * ----------- 
    16*10^6 clks   1 second   1 count   1 roll-over 

which comes out to  65.5 ms
                   ---------
                   roll-over


When you solve these problems, it's important to verify that all the units, except those that you want, cancel. We will call the time required for the counter to go from 0 to 216 - 1 and then back to 0 the maximum period of the counter. Practice using the dimensional analysis technique to determine the maximum period (in milliseconds) for all the prescalers in the following table. The maximum periods for each prescaler are shown in a previous table and rounded to 3 significant figures. You will need this table to solve practical problems of interest like the following:

Some problems

Test your understanding

You can find the solutions embedded in the "source code" for this web page by right mouse clicking on this web page and selecting "view source". The solutions are in HTML comments.
  1. With an 1:8 prescaler and an initial value of 0x1234, how long does it take the counter to reach 0xABCD?
  2. With an 1:8 prescaler and an initial value of 0xABCD, how long does it take the counter to reach 0x1234?
  3. You are running the following code-snippet. Assuming that TMR0 = 0x1234, how long does it take to exit from the while-loop? State your answer in milliseconds.
        T0CONbits.T0PS = 0b101;
        T0CONbits.TMR0ON = 1;	
        INTCONbits.T0IF = 0;	
        while(INTCONbits.T0IF == 0);
    
  4. You have been asked to rank the number of times each line of code in the following program is executed. This algorithm (introduced earlier in this lecture) measures the duration of short (< 50 ms) logic low pulses on pin RA2. You are examining the following code over 1 second, during which there was a single 30 ms logic low pulse.
        for (;;) {
    1. 	while(PORTAbits.RA2 == 1);	
    2. 	start = TMR0;
    3. 	while(PORTAbits.RA2 == 0);
    4. 	end = TMR0;
    5.	duration = end - start;
        } // end infinte loop
    
    1. Rank the lines of code, from most executed to least execute.
    2. If each line of code takes 1us to execute, provide an estimate of the number of us spent (over a 1 second period) executing each instruction.