Log in

View Full Version : General Question About Multiple Interrupts



grzeh666
- 30th August 2008, 04:23
Hi!

This is my first post on the forum. I'd like to welcome everyone and thank in advance for any help.

I have a question about multiple interrupts. I'm working on a program for 18f4525 to control buttons,led and relays via couple o MCP23S17's. MCP's communicate with 18f by STI serial protocol.I want to keep code as simple as possible and limit the use of interrupts to minimum.

My idea of the program goes like that:
When switch is pressed MCP generates interrupt to 18f. Interrupt handler will just set the variable like specyfic_interrupt = 1, and than go to main program, execute it and find the right code with if statement.

My main concern with this approach is what will happen if another interrupt will occure during execution of previously received interrupt. I mean - if the code reach the right code for interrupt and start executing it, if another interrupt would be received the program will jump to interrupt handler, thus stopping execution of previous interrupt in the middle of it.

Is this case technically possible with buttons (to switch them so fast?). If it is - is there a way to secure my program from that case ?. Is this approach good at all or should I just code complete interrupt handlers ?

Thank You very much in advance for all the suggestions.

Jerson
- 30th August 2008, 06:39
First of all, welcome to the community.

Generally, interrupts are blocking. So, if you are servicing an interrupt, another will lie pending till the first completes.

However, there may be instances where you wish to take another interrupt within another's service routine. That requires you to be crafty and know exactly what you're doing in consultation with the datasheet for that device. These instances are quite rare and can be usually ignored altogether till you seriously need them.

A rule of thumb for ISR(interrupt service routines) is to keep them small and avoid subroutine calls from within them (fast). You could use signalling from the interrupt to your mainline if you need some rudimentary messaging. eg: the keypress could be read and saved to a byte which is then read by the mainline code.

Hope these ideas are helpful to you

paul borgmeier
- 30th August 2008, 15:56
The 18F family also allows one to set some interrupts as high priority and some as low priority. If a high priority interrupt occurs, it will complete the High ISR and exit before servicing additional interrupts (unless you are crafty like Jerson noted). If a low priority interrupt occurs, it will proceed to the Low ISR and exit before serving additional low level interrupts. However, if a high level interrupt occurs while your code is in the low level ISR, the low level interrupt will be interrupted. The high level interrupt will be serviced and then the code will jump back to the low level interrupt and finish its ISR before exiting. Clear as mud?

grzeh666
- 31st August 2008, 11:22
Hello again!

Thank You for all the replies. It actually is a lot clearer to me now. I think I understand the concept much better. I will try to handle all interrupts in the system clean and fast without any calls to external sub routines.

Thank again!

greg

tenaja
- 31st August 2008, 17:09
I've used this technique with multiple interrupt sources. At the start of the interrupt routine, after saving your context (if necessary), I test all of the interrupts possible, in order of priority, and the first one ON has a goto to the handler code for that specific interrupt. (For very short handlers, you can also use short IFs or Select Case--but this is less readable if the handler code is more than just a few lines.) After these tests, I return from the interrupt... but each interrupt handler ends with a goto the test segment. That way if another interrupt occurs while I'm in a handler, then it is still handled.

Like this psuedo code...

Int_Service:
{save your context if necessary}
Int_Tests:
if Timer1IntActive = IntOn then Timer1Handler
if Timer2IntActive = IntOn then Timer2Handler
{restore context if necessary}
resume

Timer1Handler:
{handle the interrupt & reset it}
goto Int_Tests

Timer2Handler:
{handle the interrupt & reset it}
goto Int_Tests

--but, it does take up a slight bit more code. You could simply resume at the end of each handler, but then you'd have to repeat the context saving code if your interrupts occur at the same time.