previous | start | next


Timers on the ’84

The basic idea

The basic idea, is that we will want to use our ’84 to time something. Time, that is, in the way we would use a wall clock: we might switch on our fish-tank lights for instance, or close the curtains at 18h00 each night. But there’s no clock in the ’84: no clock in the wall clock sense anyway.

What there is though, is a simple relationship between the carrying out of instructions and the speed with which the processor ticks away. The book tells us [PIC p1 The page, figure, and table numbers reffered to here come from an older version of the '84 datasheet which is available at http://www.piclist.com/images/piclist/30445B.PDF the current datasheet for the modern version of the '84 is available at microchip.com] that an instruction completes in 1 cycle, namely 400ns when the processor is being clocked at 10MHz.

Let’s verify this, and introduce a handy feature of MPLAB at the same time: the Stopwatch. In MPLAB prepare to run any of the programs you have written up to now. Open the stopwatch by going Window > Stopwatch. You’ll see a simple window, containing 3 important pieces of information: the number of steps completed in what time, and at what frequency. Check that the frequency is set to 10MHz for now, click zero and step your program once. You should see that you progress to 1 cycle in 400ns. (Unless this was coincidentally a program branch, which is a 2-cycle instruction.) Experiment with various frequencies; for instance 400ns becomes 40ns at 100MHz, or 800ns at 5MHz.

So, we have the glimmerings of a wall clock type of timer here- we know how much time has passed if we know how many steps have occurred. Enter Timer0 . . .

The TIMER0 module

The PIC’84 timer, TIMER0, works on the basis that each time an instruction cycle occurs, a certain interval of time has elapsed. When TIMER0 is running, its register (TMR0) is incremented each cycle; each 400ns if the clock is a 10MHz one. Therefore, the value of TMR0 represents the ‘time’ in 400ns steps. But TMR0, like all registers, is an 8-bit one and can thus only count as high as FF: that means time only goes as far as 255 x 400ns = 102000ns or about 100 m s which is not too long. Cast your mind back to the discussion of interrupts earlier, where we said that one of the interrupt types was a timer overflow interrupt: that means that the TMR0 register has gone over the top at FF and back to 00. That means the interrupt occurs every 100m s of real time. It’s up to us to do something with this interrupt, which probably means incrementing a register of our own, clocked say: every time clocked gets to a certain value, that means 1 second of real time, and we’d probably then go off and increment another register, perhaps seconds

Let’s walk through the process, then, of simply getting TIMER0 going, using the initialize, handler, main interrupt technique used earlier.

Initialize: set GIE, INTCON<7>, to enable interrupts

set T0IE, INTCON<5>, to enable timer interrupt

clear T0CS, OPTION<5>, to enable timer- see

set PSA, OPTIOPN<3>, to keep prescaler out of this

Handler: increment ‘clocked’, our overflow counter

Main: have some trivial loop to keep the program going

Exercise: Write a program to implement the above simple timer, bearing in mind we won’t be doing anything with the timer overflows other than clicking them in clocked. Check the program in the simulator, having visible any registers you think you should monitor, also the stopwatch. Before you start, you’ll need to figure out how to access the option register, which is not quite as simple as accessing say status. I’ve explained it below. See time1.asm.

Accessing registers in Bank1: You’ll have noticed in [PIC fig 4-2, p12] that some registers like option are in what they refer to as Bank1, as opposed to Bank 0. Others, like status are in both Banks. What this means in practical terms, is that these Bank 1 registers are not normally available, because our default sphere of operations is Bank 0. We use the status register to effect a switch between banks, with RP0 & RP1 (STATUS<5> & <6>) doing the trick. This simply means that we must set RP1  [ed: this shoudl say RP0] to go to Bank1 and clear it to return. For those registers which are in both banks, you can of course access them no matter where you are, but remember the register has 2 different addresses: status is known as h’03’ and h’83’.

Using the timer’s overflow

Now we can probably see the wood through the trees: we have a register clocked which is updating whenever the timer overflows. That’s roughly every 100m s. Being an 8-bit register itself, clocked can of course only count to 255, and so it will overflow at 255 x 100m s which is 2.55 x 10-2 seconds. We’ll need to count these overflows too, into say clocked2. Now, we’re getting closer to the actual second, which is what we’re heading for: how high do we need to count in clocked2 to reach 1 second? Incrementing every .0255 seconds there are roughly 39 increments in a second , so this means, finally, we can count real-time seconds by incrementing another register, perhaps SECONDS, every 39 steps. To get to minutes and hours, we can simply overflow SECONDS into MINUTES at 60 seconds and MINUTES into HOURS every 60 minutes.

Exercise: Create a program to implement the above, at least as far as the SECONDS register.



previous | start | next

Comments: