2. Choose your prescale to come “close” to your interval
3. Calculate the timer count that comes as close as you
can to your interval.
4. Set your timer register to (maximum value – timer count).
5. Code the timer setup and its interrupt.
6. When you get your interrupt, clear it and re-set the
register to your value.
Obviously, this process could use an example. Let’s
set up a background timer on a PIC16F630 to provide us
with a 100 ms tic for our timing needs. Let’s also say that
we’re using a 10 MHz crystal on our processor, so our
clock to the timer = 10 MHz/4 = 2. 5 MHz. This would
give us a 400 ns clock which on the 16-bit TIMER1
module would be a 65536 400 ns = 26.214 ms rollover
period. Hmm. We need 100 ms, so we’re going to need
to pre-scale the clock in to slow that counter down. How
much can we slow it down?
Let’s look at the T1CON (TIMER1 Configuration)
register for our options (Figure 2). We see that we only
have four choices for a prescaler: 1:1, 1: 2, 1: 4, and 1: 8.
Since 1:1 is almost four times faster than what we want,
we’ll choose 1: 4 as our prescale. This takes our clock rate
down to 1.6 µS per count with a maximum overflow of
65536 1.6 µS = 104.86 ms. That is pretty close to what
we want. You’ll note that there are a bunch of other
options we can set for this timer but we’re not using them,
so the rest (except for bit 0: TMR1ON) will be left at 0.
More on that later when I show some code.
A full timer count is now 104.86 ms which is more
than the 100 ms that we want. So, we need to load up the
timer register with some value other than zero to come
closer. The easiest way to figure out what this number
needs to be is by doing some simple math; 100 ms/1.6 µs
= 62,500. Our timer register counts up, so that isn’t the
number we want to “pre-load” it with. We want to use
65536-62500 = 3036. Those were steps 1-4; now we need
to write code. Listing 1 shows how we would set this all
up with CCS PCM. PCM will handle clearing the interrupt
flag and setting all of the configuration registers for the
timer and the interrupt systems. That wasn’t painful, was
it? Make sure that t_100ms is a globally defined variable
that is at least 16-bit, preferably 32 bits.
Figure 3 shows the layout of T0CON. You’ll note that this
TIMER0 configuration register looks a lot like the PIC16Fxxxx
T1CON. However, this timer can be configured as either an
8-bit or a 16-bit timer. I chose 16-bit here to get a higher
resolution on the timer. Also, TIMER0 has more prescale
options on the PIC18F than we had on the PIC16F series.
The Microchip C18 compiler does not abstract the
hardware like the CCS PCM compiler does. The programmer
has a lot more control over how the interrupts work, but by
getting that control, has to do a lot more work setting bits
in the configuration registers. Listing 2 shows what we
need to do to set this timer up and configure the interrupt
handler. An interesting enhancement to the PIC18F
architecture exists in the interrupt module. The programmer
can use the Fast Interrupt option which has a one-deep
stack that holds essential information when an interrupt
Listing 1: Setup and ISR
for TIMER1 overflow.
Timers for the PIC18Fxxxx
sets up everything before I use it.
10MHz clock, external ~MCLR
The PIC18F series has a higher system clock ( 40 MHz)
and is capable of having much more Flash and RAM
memory, making them useful for larger projects. They
integrate complex hardware modules like ETHERNET and
CAN in some of them, as well. I’m going to refer to the
18F252 microcontroller which is a 28-pin part.
The procedure for figuring out our timer needs is the
same as the one given in the previous PIC16Fxxxx series
explanation. Let’s look at TIMER0 one this part and see what
may be different. I’m going to use the Microchip C compiler
for the PIC18F series (C18) for the source code example.
//Turn off comparator
//Set up TMR1
setup_timer_1(T1_INTERNAL | T1_DIV_BY_4);
//1.6us per tic
t_100ms = 0; //set up the ticker
//enable TIMER1 interrupt
//turn on the interrupts
SERVO 01.2012 15