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 theres 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.
Lets 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. Youll 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 PIC84 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. Its 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 wed probably then go off and increment another register, perhaps seconds
Lets 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 wont 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, youll need to figure out how to access the option register, which is not quite as simple as accessing say status. Ive explained it below. See time1.asm.
Accessing registers in Bank1: Youll 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 h03 and h83.
Now we can probably see the wood through the trees: we have a register clocked which is updating whenever the timer overflows. Thats 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. Well need to count these overflows too, into say clocked2. Now, were getting closer to the actual second, which is what were 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.
Comments: