Hardware Counter/Timer
Accurate event timing and counting are often needed in microcontroller programs. For example, if we have a sensor on a motor shaft that produces one pulse per revolution of the shaft, the number of pulses per second will give the shaft speed. Alternatively, the interval between pulses can be measured, using a timer, to obtain the speed by calculation. A process for doing this would be:
1. Wait for pulse.
2. Read and reset the timer.
3. Restart the timer.
4. Process previous timer reading.
5. Go To 1.
If an independent hardware timer is used to make the measurement, and the timer interrupt used, the controller program can carry on with other operations, such as processing the timing information, controlling the outputs and checking the sensor input, while the timer simultaneously records the time elapsed.
Using TMR0
The special file register timer zero (TMR0) is found in all PIC 16 devices. It is an 8-bit counter/timer register, which, once started, runs independently. This means it can count inputs or clock pulses concurrently with (at the same time as) the main program execution. A block diagram of TMR0 and its associated hardware and control registers is shown in Figure 6.3.
As an 8-bit register, TMR0 can count from 00 to FF (255). The operation of the timer is set up by moving a suitable control code into the OPTION register. The counter is then clocked by an external pulse train or, more often, from the instruction clock. When it reaches its maximum value, FF, and is incremented again, it rolls over to 00. This register overflow is
recorded by the INTCON (interrupt control) register, Bit 2 (T0IF); assuming that it has been previously enabled and cleared, it is set to 1 when TMR0 overflows. This condition can be detected by bit testing in the program, or it can be used to trigger an interrupt (see Section 6.3 below).
In many PIC chips the 8-bit TMR0 is supplemented with additional 8-bit and 16-bit counters. The latter provide an extended count (up to 65 535) that gives greater accuracy or range. These timers are typically used to measure input intervals or generate output signals with a controlled period, using a similar setup process to that described below for TMR0.
Counter Mode
The simplest mode of operation of TMR0 is counting pulses applied to the relevant input (RA4 in the 16F84A, RA2 in the 16F690), which has the alternative name T0CKI, timer zero clock input. These pulses could be input manually from a push button, or produced by some other signal source, such as the sensor on the motor shaft mentioned above. If the sensor produces one pulse per revolution of the shaft, and one of the PIC outputs controls the motor, the microcontroller could be programmed to rotate the shaft by a set number of revolutions. If the motor were geared down, a positioning system can be designed to move the output through a set angle, for example, in a robot.
In order to increase the range of this kind of measurement, the prescaler allows the number of pulses received by the TMR0 register to be divided by a factor of 2, 4, 8, 16, 32, 64, 128 or 256. The ratio is selected by loading the least significant three bits in the OPTION register as follows: 000 selects divide by 2, 001 divide by 4 and so on up to 111 for divide by 256. With the maximum rate of division set, the register will count only 1 in 256 of the input pulses. TMR0 can also be preloaded with a value, say 156, using a standard MOVWF instruction. When it has been topped up by a suitable number of pulses (100) the overflow can be detected and acted upon by the program.
Timer Mode
The internal clock is selected as the TMR0 input source by setting the OPTION register, Bit 5, to 0. For accurate timing, a crystal oscillator must be used, mode XT. With a 4 MHz clock, the instruction clock will be 1 MHz, and the counter will then be clocked every 1 ms, taking 256 ms to count from zero round to zero again. By preloading with the value 156(9Ch)
as above, the overflow would occur after 100 ms.
If the time period measured is extended using the prescaler, the maximum timer period will be 512 ms, 1024 ms and so on to 65.536 ms. Crystals are available that operate at frequencies more conveniently divisible by 2; for example, a 32.768 kHz crystal frequency
will produce an instruction clock at 8192 Hz. If this is now passed through the prescaler set to divide by 32, the counter will be clocked at 256 Hz and will time out once per second. Some PIC chips have an additional internal oscillator set to approximately this frequency (31 kHz).
In Figure 6.3, TMR0 is set up with xxx000002 in the Option register, selecting the internal clock source, with a prescale value of 2. The INTCON register has been set up with the timer interrupt enabled and the timer overflow interrupt flag has been set (overflow has occurred). Interrupts are explained in more detail in Section 6.3 below.
TIM1 Timer Program
A timer demonstration program TIM1 is listed as Program 6.1. It is designed to increment the binary output at port B once per second. The program uses the same demonstration BIN hardware as the previous programs, with eight LEDs displaying the contents of the output port. An adjustable CR clock is used, set to give a frequency of approximately 65 536 Hz. This frequency is divided by four, and is then divided by 64 in the prescaler, giving an overall frequency division of 4 x 64 ¼ 256. The timer register is therefore clocked at 65 536/
256 ¼ 256 Hz. The timer register counts from zero to 256, overflows every second, and the output is then incremented. It will take 256 s to complete the 8-bit binary output count.
Problems with TIM1
The program TIM1 works by ‘polling’ the timer interrupt bit. This means that the program has to keep checking to see if this timeout flag has been set by the timer overflowing. This is not an efficient use of processor time. In real applications, it is usually preferable to allow the processor to carry on with some other process while the timer runs, and allow the timeout condition to be processed using an interrupt. The overall performance of the MCU is thus improved.
If the program is tested in MPSIM, and the stopwatch is used to measure the output step time, using a breakpoint at the increment instruction, it measures just over one second. The extra time is taken in completing the program loop before the timer is restarted. This will cause
a small error, which may not be significant in this case, but in other applications it may be important. If the clock is adjustable (CR mode with variable resistor), overall timing can be tweaked in the hardware, or the program timing adjusted using NOPs.