Put simply, its exactly what it says: a means of getting the computers attention. Refer to the conveyor/mixer scenario mentioned earlier (p17), where we saw the following snippet of pseudocode:
. line # 40: start conveyor . . line # 63: is the level sensor switch set yet? line # 64: no- go back to line # 63 and look again line # 65: yes- stop the conveyor, then line # 66: start the mixer and carry on . .
Here, the program will loop around line 63 and 64 for ever if necessary, waiting for the vat to fill up. Thats OK, the programs job is to run the process! Well, true, but its wasteful. It might take a few seconds, minutes or hours to fill the vat; we could have the program doing something useful while its waiting. But if the programs off somewhere else- doing the payroll?- and the switch closes, how will the program know? Its not looking.
Same way as you get someones attention when you come to visit. Theyre not standing looking out the front door all day, theyre going about their daily business; your knock on the door interrupts this, and they come to the door.
Our program would look something like this:
. line # 40: switch on the conveyor . line # 50: do some payroll work line # 51: and some more, and stay up here until interrupted . . . line # 60: only come here when interrupted line # 61: stop the conveyor line # 62: switch on the mixer line # 63: go back to where you were when you got sent here
Now, the program spends most of its time in the payroll section, not looking at the switch in the vat. When the switch closes, the hardware takes care of things: the switch is connected to the computer by the interrupt request line (IRQ), and program control is passed to a predetermined point. That point is line # 60 in the example above, and what happens at line 60 is up to the program/mer.
Notice something crucial here: once the interrupt has been taken care of, control must go back to where it was earlier. Not only that, but the state of the system must be put back: if any registers were changed while handling the interrupt, they must be restored. Well look into this later.
Now we know what an interrupt is in concept, we can look at how the 84
allows for this notion.
Types of Interrupt and the INTCON register
The 84 has 4 different types of interrupt [PIC p44] [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] :
an external interrupt on pin 6, aka RB0
a change on any of pins 10-13, aka RB4-7
a timer overflow
an EEPROM write complete.
(Of these 4 types, the first one is the kind wed use in the above conveyor/payroll program.)
In order to allow interrupts, and to determine the source thereof, the processor uses the INTCON register (0Bh) whose contents are detailed in [PIC table 4-5], and which Ill explain here. Each bit serves a specific purpose, and interrupts work according to the value (set or clear) of the various bits.
Firstly, interrupts as a whole may be enabled or disabled by INTCON<7>, the GIE (Global Interrupt Enable) bit. If this bit is clear, then no interrupts may occur: this is the power-up value by the way. Also, if an interrupt occurs, then GIE is cleared to prevent the interrupt being interrupted; returning from the interrupt with the retfie instruction re-enables interrupts.
Second, each of the interrupt types must be enabled with its own bit in INTCON, before it can be used:
external interrupt on pin 6: INTCON<4>, the INTE bit
change on any of pins 10-13: INTCON<3>, the RBIE bit
timer overflow: INTCON<5>, the T0IE bit
EEPROM write complete: INTCON<6>, the EEIE bit.
Third, when interrupts occur, certain bits (known as interrupt flags)are set so that we may determine the source of the interrupt:
external interrupt on pin 6: INTCON<1>, the INTF bit
change on any of pins 10-13: INTCON<0>, the RBIF bit
timer overflow: INTCON<2>, the T0IF bit.
Why do we need to know the source? Well, depending on the type of interrupt,
we will take different action: checking the appropriate bit tells us which
interrupt it is. Note that the interrupt flags always get set when theres
an interrupt, regardless of the state of the corresponding enable bit.
In the conveyor/payroll example above, there must be a means of sending the program to the right place to sort out the interrupt; line 60 in the example. How does the processor know where to go? In the PIC84, all interrupts are sent to 0004h: in the parlance of microprocessors, this point is the interrupt vector, and the program is said to vector there. At the vector, we must make sure that we provide whatever code is necessary to take care of the problem.
A crucial point is that we might need to save the status of the machine as it was before interruption, before we service the interrupt. Clearly, the activities undertaken during servicing could change such things as the W & STATUS registers; we would need these restored after handling the interrupt, in order that our other work may resume. The 84 only saves the PC to the stack (PC+1, actually), and its up to us to ensure we save and restore anything else we need!
Lets walk through a scenario in pseudocode, without yet looking at the 84 code. Foster suggests 3 parts to a program which must handle simple interrupts: an initialize section, where in our case well enable the interrupts; a main section, where the bulk of the time is spent (doing the payroll, or whatever) and the handler part where the interrupt is taken care of.
Initialize:
Handler:
Main: do the payroll calculations
Exercise: Start slowly with interrupts- this can get quite hairy. Write a program to provide the absolute minimum interrupt ability: enable them, have an interrupt service routine that does little if anything other than re-enable interrupt and then return, and a main part that merely loops through some meaningless code waiting for an interrupt. You need not save the status of the machine, nor check for the type of interrupt at this stage. In order to see this program working properly in the simulator, I suggest using the interrupt on change in port b, using the asynchronous stimulus technique discussed before. Use a toggle on the pin to effect the change: while the program is looping in the main section, toggle the pin and check that the interrupt occurs when you next step the program. While the program is then in the isr, toggle the pin again: if its all working, the pin change will not cause an interrupt, because GIE will have been cleared. See inter1 . asm.
Exercise: Now add to the program, to save the state of the machine at the interrupt. To test this, make sure you load W (say) in the main part, then change it in the ISR, and check that it gets restored properly. Hint: see [PIC p46, example 8-1]. See inter2.asm
Exercise: Finally, allow for more than 1 kind of interrupt- change on one of portb pin 4:7 as well as an interrupt on the rb0/int pin. Now, youll need to determine the kind of interrupt, and handle it accordingly. See inter3.asm.