Interrupts
From MARS Wiki
Contents |
What is an interrupt?
An interrupt is a way for hardware -- rather than software -- to trigger a call to a subroutine. What this means is that each time a hardware counter overflows or an external pin changes state, the processor will jump to some predefined memory location and run the code located there.
Why do we care?
Interrupts make it easier to multitask. Your code can be chugging along doing one thing and still respond to external stimuli in a timely fashion.
Interrupts on the PIC16F628A
There are several things that need to be set up before we can depend on interrupts.
Timer0
Timer0 is an 8-bit timer/counter register that can be used to trigger interrupts. It can be configured to increment after the execution of each instruction or with each transition on the RA4/T0CKI pin of the chip. When all the appropriate registers are configured, it generates an interrupt every time it overflows from 255 to 0.
The OPTION register
The OPTION register is where we configure the prescaler. The prescaler is a divider that it inserted between Timer0 and its clock source. Its sole purpose is to make Timer0 interrupts occur less frequently. For our applications as an LED blinker, we set the prescaler to the maximum possible value, 1:256.
The INTCON register
We also have to set up the INTCON register to enable interrupts. It is here that we enable the Timer0 interrupt and also enable interrupts for the entire chip by setting a couple of bits correctly.
Code organization
On the PIC16F628A, an interrupt will always generate a call to the subroutine located at program address 4. This means that our code should look something like the following:
org 0 goto start ;jump over the interrupt service routine for now org 4 ;put all the interrupt code here retfie start ;continue booting the processor . . . end
Saving and restoring program context
Another major point is keeping track of what the processor was doing before the interrupt took place. If there was a certain value in W, we should keep it there lest the interrupted program get "confused." At a bare minimum, we need to back up the W and STATUS registers to maintain CPU state when we return from the interrupt. We can use the following code to do that:
;Note: This code assumes that two memory locations '_w' and '_s' have been defined. org 4 movwf _w swapf status,w movwf _s . . ;rest of interrupt code goes here . swapf _s,w movwf status movf _w,w retfie
This code will immediately save W upon entry into the interrupt service routine, then it saves the STATUS register in such a way that the STATUS register is not changed in the process. The process is reversed at the end of the interrupt routine -- STATUS is restored, followed by W. Doing it in this order makes sure that W contains the correct data when the main program is returned to.
