How to Handle Multiple Interrupts in Embedded C Correctly
To handle multiple interrupts in
embedded C, assign each interrupt a unique ISR (Interrupt Service Routine) and configure interrupt priorities if supported. Use volatile variables and clear interrupt flags inside each ISR to avoid conflicts and ensure proper execution.Why This Happens
When multiple interrupts occur, if ISRs are not properly separated or interrupt flags are not cleared, the system may behave unpredictably or miss interrupts. This happens because the microcontroller might not know which interrupt to handle first or may keep re-entering the same ISR.
c
#include <avr/io.h> #include <avr/interrupt.h> volatile int count1 = 0; volatile int count2 = 0; ISR(INT0_vect) { count1++; // Missing flag clear or improper handling } ISR(INT1_vect) { count2++; // Missing flag clear or improper handling } int main(void) { // Enable INT0 and INT1 interrupts EIMSK |= (1 << INT0) | (1 << INT1); sei(); while(1) { // Main loop } return 0; }
Output
System may miss interrupts or behave unpredictably due to improper flag clearing and no priority handling.
The Fix
Assign separate ISRs for each interrupt and clear the interrupt flags inside each ISR. If your microcontroller supports interrupt priorities, configure them to decide which interrupt runs first. Use volatile variables to safely share data between ISRs and main code.
c
#include <avr/io.h> #include <avr/interrupt.h> volatile int count1 = 0; volatile int count2 = 0; ISR(INT0_vect) { count1++; EIFR |= (1 << INTF0); // Clear INT0 interrupt flag } ISR(INT1_vect) { count2++; EIFR |= (1 << INTF1); // Clear INT1 interrupt flag } int main(void) { // Configure INT0 and INT1 as needed EIMSK |= (1 << INT0) | (1 << INT1); // Enable INT0 and INT1 sei(); // Enable global interrupts while(1) { // Main loop can use count1 and count2 safely } return 0; }
Output
Interrupts handled correctly with counts incremented and flags cleared.
Prevention
To avoid issues with multiple interrupts, always:
- Use separate ISRs for each interrupt source.
- Clear interrupt flags inside each ISR to prevent repeated triggers.
- Use
volatilefor variables shared between ISRs and main code. - Configure interrupt priorities if your hardware supports it to control execution order.
- Keep ISRs short and efficient to avoid blocking other interrupts.
Related Errors
Common related errors include:
- Interrupt nesting issues: Not enabling nested interrupts when needed can block higher priority interrupts.
- Race conditions: Accessing shared variables without
volatileor atomic operations causes inconsistent data. - Interrupt flag not cleared: Causes the ISR to be called repeatedly, freezing the system.
Key Takeaways
Assign unique ISRs for each interrupt source to avoid conflicts.
Always clear interrupt flags inside the ISR to prevent repeated triggers.
Use volatile variables for data shared between ISRs and main code.
Configure interrupt priorities to control which interrupt runs first.
Keep ISRs short and efficient to allow smooth handling of multiple interrupts.