A. Your best friend is flying into town today,
and you're supposed to pick him up at the airport. Unfortunately, you
don't know when exactly his plane is arriving. You didn't make any prior
plans to have him call you when his flight came in, so to figure out
when he arrives, you must call his cell phone every 15 minutes or so.
Of course, as soon as he lands you can assume he will turn his cell
phone on - your call will go through, and you will know he has arrived.
So there you are, calling him every 15 minutes throughout the day until
he lands. After several hours of this (you're a dedicated friend!) you
finally get a ring, and he answers. You go and pick him up.
B. Your best friend is flying into town today,
and you're supposed to pick him up at the airport. Unfortunately, you
don't know when exactly his plane is arriving, but, clever person that
you are, you asked him to call you as soon as he landed. So you go about
your business all day without worrying about when his plane is coming
in - and sure enough, as soon as he lands he calls you, and you're on
your way to pick him up.
Obviously scenario "B" is generally the more preferable
of the two. Why? The primary reason is efficiency with resources
- the primary resource in this case being your time.
The two scenarios are analogous to the two methods available for
letting a microcontroller know when a hardware (or sometimes software)
event has occurred that it must process. In both scenarios, you are
the processor, and your friend is the hardware that needs to be processed.
Scenario "A" corresponds to polling - that is,
the processor constantly "asking" the hardware if something
has happened. Scenario "B" corresponds to interrupts
- that is, the hardware interrupts the processor to tell
it a hardware event has occurred. Here's another way to look at it:
Polling:
Processor: "has he pushed the button yet?!"
Hardware: "no"
Processor: "has he pushed the button yet?!"
Hardware: "no"
Processor: "has he pushed the button yet?!"
Hardware: "no"
a long time later...
Processor: "has he pushed the button yet?!"
Hardware: "no"
Processor: "has he pushed the button yet?!"
Hardware: "no"
Processor: "has he pushed the button yet?!"
Hardware: "YES!!! PROCESS! PROCESS!"
Processor: "Roger that! Processing!!"
Interrupts:
Processor: "hmmm dum dum, just doing my business, running
my program, hmmm hmm dum, just executin' code, no worries in the
worl...."
Hardware: "WE HAVE AN EVENT!!"
Processor: "Roger that! I'm on it!!"
The polling method can actually be the better choice sometimes
- for example, if the processor has very little else to do besides
pay attention to a couple of hardware events, then you might actually
lose efficiency if you try to use interrupts, because interrupts do
require a certain amount of overhead. For example, if you are making
a digital thermometer, it would make more sense to "read
sensor, output value; read sensor, output value; read sensor, output
value" etc, then it would to have the code execute a nop
loop until the sensor changed, then signaling the processor to read
the new value of the sensor and update the display.
Interrupts come into their own in situations where some event takes
place relatively infrequently. For example, say the thermometer had
a button to toggle between Celsius and Fahrenheit. Since the user
will probably push that button very rarely - if ever - why would you
want to waste time "asking" the button every few microseconds
if the user has pressed it? You wouldn't! You'd want the processor
to focus on it's primary task, and momentarily interrupt
it from that task only when the button was actually pressed.
Every processor except the most basic - from the low end PIC MCU's
to the cutting edge Intel and AMD models are capable of utilizing
interrupts. You've probably heard of IRQs in regard to home computers
- these are Interrupt Request Lines - and they are the pathway
by which various pieces of hardware (i.e. the keyboard or mouse) notify
the processor of an event (i.e. a keypress or mouse move).
PIC Interrupts
PIC MCU's allow several kinds of interrupts, depending on the model
you are using. For example, on most models, several port pins can
be configured to provide an interrupt-on-change function.
That is, then the state of an input pin changes from low to high,
or high to low, the processor will jump to a special interrupt
service routine (ISR) to handle the event. There are also events
that may occur internally - most PIC's include internal timers that
will generate an interrupt after a pre-set number of clock cycles
have occurred, allowing for precise timing independent of what the
rest of the program is doing.
There are many others - straight from the 16F630 / 676 data sheet:
• External Interrupt
RA2/INT
• TMR0 Overflow Interrupt
• PORTA Change Interrupts
• Comparator Interrupt
• A/D Interrupt (PIC16F676 only)
• TMR1 Overflow Interrupt
• EEPROM Data Write Interrupt
Again - this is far from
an all-inclusive list, as the capabilities vary from model to model.
The ISR
So what actually happens when the hardware interrupts the
processor to tell it an event has occurred? How does the processor
"answer it's phone," so to speak?
There are several registers in the PIC in which each bit is an interrupt
flag, corresponding to the hardware that caused the ISR to "fire."
When one of these flags is set, there is a hardware-induced jump to
the ISR routine, which is always located at 0x0004. You must write
the ISR to determine, based on the interrupt flags set, what actually
caused the interrupt, and act accordingly. Further - you must specify
to the linker that that particular section of code must
start at 0x0004.
Well, that's it for the conceptual introduction to interrupts. For
a tutorial on putting these abstractions into practice, see the next
tutorial!
top