Interrupts Or Polling?


Read The Facts


From reading different robot forums on the net it is very clear to me that many people have the wrong ideas about interrupts. People are making statements that are totally wrong.

I am going to side track for a little here. Three people go to the movies. One person says he loved the movie. The 2nd person say the movie was just O.K. The 3rd person says it was the worst movie he has ever seen. Who right? They all are. It is just a matter of taste etc.

Three children are taking a test. The question is 2 + 2 =

The 1st child says it's 3. The 2nd says it's 4. The 3rd says it's 5. Who's right? The 2nd child is right.

Programming is NOT like going to the movies. It is NOT just a matter of taste. Programming is like math. An instruction takes X amount of time. Put some intructions together and make a routine. That routine is going to take X amount of time. So you can prove if your program will work better using interrupts or not. What do I mean by better? If your program does everything you want it to and does it faster than another program then that program is better.

Lets me first say what I mean by "polling", since that word is used a lot. When you seek and get information from an output; that's "polling".

O.K. lets find out what an interrupt really is. Let me 1st say that interrupts work a little different from chip to chip and from CPU to microcontrollers. In a CPU interrupts can get complicated so I am just going to give you the highlights. When there is an interrupt the cpu stores the address it is at, to a place in memory called a stack. Then the cpu jumps to a place in memory called a vector table. The vector table (most of the times) holds the address of where the cpu will jump to to run what is call an interrupt service routine. The cpu has more than one type of interrupts. They are given numbers. So interrupt 1 will jump to a different address in the vector table than interrupt 2.

Now in a PIC microcontroller there is no vector table. The interrupts go to the same address. It is up to you the programmer to find out what cause the interrupt. If you only use one interrupt then it is easy. If you happen to used 2 or more different interrupts; then you have to check the PIC's registers and read out the information to see what made the interrupt. So guess what; all the people who said they only use interrupts when programming a microcontroller because polling takes too much of the microcontroller resources. You are using polling, you just didn't know it.

Another statement made was that if you made a program to turn off a microwave oven you would have to use an interrupt. Lets break that down. You press in the button to tell the microwave to stop and release the latch. Human input is most likely the slowest input going to the microcontroller. Let say it took 1/20 of a sec. to press in the button on the microwave. By that time a PIC running at 8 Mhz could have done 100,000 instructions (I believe I did the math right). So it nonsense to say you have to use an interrupt.

Another statement made was that if you know how to program you don't have to use interrupts. Ok lets see if that is true. Lets say you are running a PIC at 8 Mhz and you are not using any other hardware to help it out. You are using 5 pins on the PIC for inputs. In one second's time you know at some point there will be 5 pulses coming in. All the pulses are high for 10 ms. Do you need to use an interrupt to "see" all the pulse. The answer is no, polling would work fine.

Lets say you have the same setup as above but this time one of the pulses only will stay high for .5 us. If you only used polling you could not "see" a pulse that is that short. On the other hand a PIC's interrupt circuit can "see" a pulse that is that short. So that statement is false.

Another place where an interrupt shines is in keeping things in sync. If you have 2 PIC that have no hardware for communications. The best way for the two to communicate is by using interrupts.

You could easily write a book on how to program but I have no desire to do so. So here are some tips.

Interrupts take time. Remember just because the microcontroller itself is storing the address of where it is at and then jumping to another address doesn't mean it's not taking time to do this. After the microcontroller gets to the interrupt vector location; the programmer may write something like this:

ORG 0x004 ; interrupt vector location
;SAVE REGS
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf pclath_temp ; save off contents of PCLATH register


;Remember if you are using more that one type of
;interrupts you still need to write a routine to find
;what interrupt got you here and then jump to that
;service routine


;---- Do the routine you came here to do ----

;RESTORE REGS
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f ;USED SO THAT FLAGS DON'T CHANGE
swapf w_temp,w ;restore pre-isr W register contents
;Global Interrupt are able again by retfie
retfie ; return from interrupt
;--------- END OF interrupt ROUTINE ---------------

Also remember that the "retfie" is a two cycle instruction.

How might this look if you were using polling:

BTFSS PORTA,5 ;TEST PIN 2 FOR NEXT High
GOTO WAITFOR1STH ;go to some other place in the program
;---- Do the routine you came here to do ----
;--------- END OF POLLING ROUTINE ---------------


Well the 1st thing a person should say is that you have to keep coming back to the polling routine to "see" when the pin goes high. When using interrupts you don't have to do this. True, but ... A good programmer knows the timing of all the signals in his project. Let me say that again. A good programmer knows the timing of all the signals in his project.

Let say within 1 ms there is going to be a pulse on a pin on your microcontroller. You want to know if the pulse is 1 ms or 3 ms long.

If done with polling it may look something like this:

;----------- START OF POLLING ROUTINE ------------------
do poll1 if pin is low goto another part of the program that will take .9 ms to do and then come back here.

if pin is high goto another part of the program that will take .9 ms to do then goto poll2

do poll2 if pin is low the pulse is 1 ms long. if pin is high the pulse is 3 ms long.

;----------- END OF POLLING ROUTINE ------------------

Now lets do it with a programmer who is going to do it with interrupts and doesn't care how the program works, just as long that it does. It may look something like this:

;----------- START OF INTERRUPT ROUTINE --------------

Do the setup routine so that when there is a change on the pin it will cause an interrupt

Do the timer setup routine.

Set program flag high

Start running the main routine.

There was an interrupt, do:

ORG 0x004 ; interrupt vector location
;SAVE REGS
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf pclath_temp ; save off contents of PCLATH register



;service routine if program flag is low skip over Start the timer

Start the timer

if program flag is high skip over Stop the timer

Stop the timer and read data

If counter > 200 it was a 3 ms pulse else it was a 1 ms pulse

set program flag low

;RESTORE REGS
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f ;USED SO THAT FLAGS DON'T CHANGE
swapf w_temp,w ;restore pre-isr W register contents
;Global Interrupt are able again by retfie
retfie ; return from interrupt
;--------- END OF interrupt ROUTINE ---------------

Keep running in main program

There was an interrupt, do:

ORG 0x004 ; interrupt vector location
;SAVE REGS
movwf w_temp ; save off current W register contents
movf STATUS,w ; move status register into W register
movwf status_temp ; save off contents of STATUS register
movf PCLATH,w ; move pclath register into w register
movwf pclath_temp ; save off contents of PCLATH register


;service routine
if program flag is low skip over Start the timer

Start the timer

if program flag is high skip over Stop the timer

Stop the timer and read data

If counter > 200 it was a 3 ms pulse else it was a 1 ms pulse

set program flag low

;RESTORE REGS
movf pclath_temp,w ; retrieve copy of PCLATH register
movwf PCLATH ; restore pre-isr PCLATH register contents
movf status_temp,w ; retrieve copy of STATUS register
movwf STATUS ; restore pre-isr STATUS register contents
swapf w_temp,f ;USED SO THAT FLAGS DON'T CHANGE
swapf w_temp,w ;restore pre-isr W register contents
;Global Interrupt are able again by retfie
retfie ; return from interrupt
;--------- END OF interrupt ROUTINE ---------------

;----------- END OF INTERRUPT ROUTINE --------------

The progam using an interrupt took a lot longer to run and it used one timer.

You may say that the progam using the interrupt could tell you exactly how long the pulse was. Yes, that is true but in this case I didn't need to know and that is why I had to add the statement "If counter > 200 it was a 3 ms pulse else it was a 1 ms pulse"

You may ask, in the real world where would you not want to know exactly how long the pulse was?

In I.R. communication. A 1 ms pulse might stand for a zero data bit. A 3 ms pulse might stand for a one data bit. There is no reason to know exactly how long the pulse was. You just needed to know if the pulse was the 1 ms pulse or 3 ms pulse.

There are problems you have to watch out for when using interrupts. One interrupt can interrupt another interrupt's service routine. If this happens at too many levels the PIC will run out of stack memory. If this happens the PIC will run at the wrong address and there goes your program.

Even if the PIC doesn't run out of stack space, it can still make problems for your program.

Say you wanted an interrupt to start a timer. Before the interrupt's service routine started the timer there was another interrupt and that interrupt's service routine was yet interrupt again (yes this can happen if you start using interrupts with out thinking about what can happen). Say the other service routines have been taken care of and you are back to the service routine that starts the timer. The timer starts. So you are saying what was the big deal. Well the big deal is when your program reads the timer it may say it's 151 but the timer didn't turn on when it should have. So the real count should have been 198. Is your robot not going to where the ball is sometimes but you don't know why? Yes, I said sometimes. Sometimes the interrupts may interrupt each other and other times not.

Unless you have some knowledge and the right tools; debugging a program that uses interrupts can be hard. If you step thru all the routines they will all work fine.

In real life you most likely wouldn't allow the timer service routine to be able to be interrupted. Which brings us to the other subjects. Interrupts can be programmed not to be able to be interrupted. So you say lets program all the interrupts that way. Well now you may have a long service routine running and the timer service routine is blocked from running. You may say have you not heard of an interrupt controller. Yes, but the PIC doesn't have one.

If you know how, you could use program flags and give a priority levels to the service routines in the software but now you are even adding more time to the time it takes to run the interrupt.

You may be asking well I use "C" to program the PIC. You said you should know the timing of your project. I just can't look up how long a statement is going to take. Maybe not but you can write a little program that can start a timer, run your "C" routine and then have the timer stop when the routine is over. That way you will know how long your routine is taking.

Well I hope this tutorial helps.