0
0
Power-electronicsProgramBeginner · 2 min read

Embedded C Program to Toggle LED on Interrupt

Use an interrupt service routine with 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

InputExternal interrupt triggered once
OutputLED toggles from OFF to ON
InputExternal interrupt triggered twice
OutputLED toggles from OFF to ON, then ON to OFF
InputNo interrupt triggered
OutputLED remains OFF
🧠

How to Think About It

To toggle an LED on interrupt, first configure the interrupt pin and enable the interrupt. Then write an interrupt service routine (ISR) that changes the LED state by flipping its output pin. This way, every time the interrupt fires, the LED changes from ON to OFF or OFF to ON.
📐

Algorithm

1
Initialize LED pin as output and set it OFF
2
Configure external interrupt pin and enable interrupt
3
Write ISR to toggle LED pin state
4
Enable global interrupts
5
Wait for interrupt events to toggle LED
💻

Code

embedded_c
#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
}
Output
No console output; LED toggles on each external interrupt
🔍

Dry Run

Let's trace toggling LED on first interrupt trigger through the code

1

Setup

PB0 set as output, LED OFF (PORTB bit 0 = 0), INT0 interrupt enabled

2

Interrupt Triggered

External event causes INT0 interrupt

3

ISR Runs

ISR toggles PORTB bit 0 from 0 to 1, LED turns ON

4

Return to Main

Program returns to main loop, LED remains ON until next interrupt

StepPORTB bit 0 (LED)
Initial0 (OFF)
After 1st interrupt1 (ON)
After 2nd interrupt0 (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

Use Pin Change Interrupt
embedded_c
#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
}
Pin change interrupts can detect changes on multiple pins but may be less precise than external interrupts.
Use Timer Interrupt to Toggle LED
embedded_c
#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
}
Timer interrupts toggle LED at fixed intervals without external events.

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.

ApproachTimeSpaceBest For
External InterruptO(1)O(1)Event-driven LED toggle
Pin Change InterruptO(1)O(1)Multiple pin change detection
Timer InterruptO(1)O(1)Periodic LED toggle
💡
Always enable global interrupts with sei() after configuring your interrupt sources.
⚠️
Forgetting to set the LED pin as output or not enabling global interrupts causes the LED not to toggle.