I have written a lengthy post about how interrupts work on the Atmega:
Any constructive comments welcome.
I have written a lengthy post about how interrupts work on the Atmega:
Any constructive comments welcome.
Informative and interesting. Thanks!
Good work, Nick. Since millis() comes up in a couple places, as a bit of an aside, I might expand just a bit on the mechanism. Folks might find it interesting to know that while their sketch is running, the processor is already being interrupted nearly 1000 times per second for the purpose of keeping time. And it's another example of how interrupts can be used.
Good idea. I've added a paragraph at the end to explain that.
external interrupts need a good signal (5V 0V) to be triggered. A long wire can disrupt signal squarenes.
something about bouncing switches and interrupts might be useful ... (One IRQ?? I got 15!!)
enabling irq's within an ISR can give rise to reentry of the same ISR. Not trivial to handle though ...
length of irq's versus frequency ... (short flag setting IRQ's are preffered)
Much Appreciated thank you for putting precious time into it, I have read a lot there.
robtillaart:
external interrupts need a good signal (5V 0V) to be triggered. A long wire can disrupt signal squarenes.
something about bouncing switches and interrupts might be useful ... (One IRQ?? I got 15!!)
enabling irq's within an ISR can give rise to reentry of the same ISR. Not trivial to handle though ...
length of irq's versus frequency ... (short flag setting IRQ's are preffered)
I mentioned about the re-entrancy, and how it is best just to set a flag. However I extended the post to show an example of debouncing. Useful idea, as interrupts can be confusing if you expect one button press but get 20. ![]()
This is great, Nick. I have vainly looked in various Arduino books for this kind of info on interrupts. Thanks for putting it out there.
I am interested in using the interrupts on "any pin" -- the PCINTx stuff; it would be good to get a little bit more on how to differentiate different interrupts on the same "port"; maybe an example or some other pointer to an example. I am concerned about the interaction with pins I am not using for interrupts; whether there are uses that cannot be combined with interrupt usage etc. Will I be triggering a PCINT2 ISR if I am using pin D4 for PWM output, and pins D5 and D6 for interrupts?
jgg3:
This is great, Nick. I have vainly looked in various Arduino books for this kind of info on interrupts. Thanks for putting it out there.I am interested in using the interrupts on "any pin" -- the PCINTx stuff; it would be good to get a little bit more on how to differentiate different interrupts on the same "port"; maybe an example or some other pointer to an example. I am concerned about the interaction with pins I am not using for interrupts; whether there are uses that cannot be combined with interrupt usage etc. Will I be triggering a PCINT2 ISR if I am using pin D4 for PWM output, and pins D5 and D6 for interrupts?
Not if things are set up properly. The PCICR register has three bits that enable pin change interrupts on a port-by-port basis. Then there are three mask registers (one for each port) PCMSKn which enable the interrupts on a pin-by-pin basis. The tricky part is that there is no built-in facility to indicate exactly which pin caused the interrupt. The PCIFR register has flags to indicate which port caused the interrupt, but again, only three bits. So I might have the ISR save a copy of the PORTx register, so that the bits can be compared to determine the pin that caused the interrupt.
Great, that is the info I was missing. Nick, it would be great if you could add that stuff about the masking to your writeup.
I don't really have a problem with figuring out which pin (which is to say, I haven't tried it yet ...), but being able to mask out the pins that I am using for other purposes is what I was after.
jgg3:
Great, that is the info I was missing. Nick, it would be great if you could add that stuff about the masking to your writeup.
Good deal. All Things Are In The Datasheet XD Nick might want to stop somewhere short of replicating the whole thing though. I could see maybe a general discussion of interrupt mask and flag registers because they are a recurring theme, but I'm not sure he wanted to get down to the bit-biting level. OTOH it can be difficult not to do that when playing with interrupts. Not sure which way is best.
I don't really have a problem ... (which is to say, I haven't tried it yet ...)
Haha, I like that! Might have one of those t-shirts around here somewhere!
Great work. Some details I would add:
Other reasons to use interrupts:
The interrupt event queues will hold at most 1 event per eventsource
ISRs will be much slower to start if processor has to wake up from deep sleep - because the oscillator needs to stabilize.
To be honest I didn't want to get too bogged down in detail, although interrupts can be complex enough. Also, I haven't done much with pin change interrupts. I regard them as a bit of a "fallback" if you can't use the dedicated interrupt pins. There are a few pin change libraries around, it could be helpful to check them out. A problem, if it is a problem, is that libraries tend to hide what is really happening from you. So a library can be great if you want a quick solution, but not so great if you want to understand what is really happening.
I've amended the page a bit to incorporate both of your suggestions (Udo and Jack), that is, the pin changes, and the waking etc.
The page currently mentions that, as follows:
The ones that set a flag could be regarded as being queued, as the interrupt flag remains set until such time as the interrupt routine is entered, at which time the processor clears the flag. Of course, since there is only one flag, if the same interrupt condition occurs again before the first one is processed, it won't be serviced twice.
Thanks for the feedback. ![]()
Interrupts VS polling - SPEED
For a routine that has to run NOW like an encoder input.
If anyone has experience programing other devices or computers - Interrupts are like events in Windows and other operating systems. The program doesn't have to wait for the interrupt event to happen but can continue doing whatever, and the interrupt routine will do its thing when the interrupt condition (HIGH, RISING, FALLING, LOW, CHANGE) is met.
Oh, I wanted to write that... just skimmed it now, certainly seems comprehensive (when is it too large and when is it the essentials?). I happened across one part at the end: Yes the Arduino 1.0 DOES use interrupts to handle Serial output as a background activity. (checked the core code). So you comment about believing it, can be less relgious ![]()
Great work.
kf2qd: if speed matters tight polling will trigger significantly faster than interrupts. The issue is that tight polling will lock the CPU for other tasks. But for raw speed polling is the way to go. I used this at least once to get sub microsecond precise timing. All interaction was put into interrupts such that the main loop could run in a super tight polling loop.
OK I removed "I believe" - now that's the name of a song, right?
As for speed, I tried to cover that in an added paragraph. Polling is faster for checking a single thing, where you can get around 1 uS performance (to do that, you have to get your checks done in 16 clock cycles, or around 8 instructions, depending on what they are exactly).
But once you start wanting to check multiple inputs, then the polling will be slower. And of course, you can't do much, or anything, else whilst polling.
I know. And I also know that the Arduino clock is usually worse than 10ppm accurate --> everything longer than one second makes microsecond precise timing much harder
I was just stabing those comments like "need maximum performance", "react now", ...
Nick
Thanks for this post
Best regards
Jantje