Embedded C Program to Toggle LED on Interrupt
ISR() to toggle the LED pin inside the interrupt handler, for example: PORTB ^= (1 << PB0); toggles LED on pin PB0 when the interrupt occurs.Examples
How to Think About It
Algorithm
Code
#include <avr/io.h> #include <avr/interrupt.h> // Initialize LED on PB0 and external interrupt INT0 int main(void) { DDRB |= (1 << PB0); // Set PB0 as output for LED PORTB &= ~(1 << PB0); // LED OFF initially EICRA |= (1 << ISC01); // Trigger INT0 on falling edge EIMSK |= (1 << INT0); // Enable INT0 interrupt sei(); // Enable global interrupts while(1) { // Main loop does nothing, LED toggled in ISR } } ISR(INT0_vect) { PORTB ^= (1 << PB0); // Toggle LED on PB0 }
Dry Run
Let's trace toggling LED on first interrupt trigger through the code
Setup
PB0 set as output, LED OFF (PORTB bit 0 = 0), INT0 interrupt enabled
Interrupt Triggered
External event causes INT0 interrupt
ISR Runs
ISR toggles PORTB bit 0 from 0 to 1, LED turns ON
Return to Main
Program returns to main loop, LED remains ON until next interrupt
| Step | PORTB bit 0 (LED) |
|---|---|
| Initial | 0 (OFF) |
| After 1st interrupt | 1 (ON) |
| After 2nd interrupt | 0 (OFF) |
Why This Works
Step 1: Configure LED Pin
Set the LED pin as output using DDRB |= (1 << PB0); so we can control it.
Step 2: Enable Interrupt
Configure external interrupt INT0 to trigger on falling edge and enable it with EIMSK |= (1 << INT0);.
Step 3: Toggle LED in ISR
Inside the interrupt service routine ISR(INT0_vect), toggle the LED pin using PORTB ^= (1 << PB0); to flip its state.
Alternative Approaches
#include <avr/io.h> #include <avr/interrupt.h> int main(void) { DDRB |= (1 << PB0); // LED output PORTB &= ~(1 << PB0); // LED OFF PCICR |= (1 << PCIE0); // Enable pin change interrupt 0 PCMSK0 |= (1 << PCINT0); // Enable interrupt on PCINT0 (PB0) sei(); while(1) {} } ISR(PCINT0_vect) { PORTB ^= (1 << PB0); // Toggle LED }
#include <avr/io.h> #include <avr/interrupt.h> int main(void) { DDRB |= (1 << PB0); // LED output PORTB &= ~(1 << PB0); // LED OFF TCCR0A = 0; // Normal mode TCCR0B = (1 << CS02) | (1 << CS00); // Prescaler 1024 TIMSK0 |= (1 << TOIE0); // Enable overflow interrupt sei(); while(1) {} } ISR(TIMER0_OVF_vect) { PORTB ^= (1 << PB0); // Toggle LED }
Complexity: O(1) time, O(1) space
Time Complexity
The interrupt toggling runs in constant time with no loops, so it is O(1).
Space Complexity
The program uses fixed registers and no extra memory, so space complexity is O(1).
Which Approach is Fastest?
Using external interrupts is fastest for event-driven toggling; timer interrupts add periodic toggling but use CPU cycles regularly.
| Approach | Time | Space | Best For |
|---|---|---|---|
| External Interrupt | O(1) | O(1) | Event-driven LED toggle |
| Pin Change Interrupt | O(1) | O(1) | Multiple pin change detection |
| Timer Interrupt | O(1) | O(1) | Periodic LED toggle |
sei() after configuring your interrupt sources.