0
0
Power-electronicsHow-ToBeginner · 4 min read

Wake Up from Sleep Mode Using Interrupt in Embedded C

To wake up from sleep mode using an interrupt in embedded C, configure the microcontroller to enter sleep mode with sleep_cpu() and enable an external or internal interrupt that triggers a wake-up. When the interrupt occurs, the microcontroller exits sleep mode and executes the interrupt service routine (ISR).
📐

Syntax

To use interrupts for waking up from sleep mode, you typically use these steps:

  • sleep_enable(): Enables sleep mode.
  • sleep_cpu(): Puts the microcontroller into sleep.
  • sei(): Enables global interrupts.
  • ISR(vector): Defines the interrupt service routine that runs on interrupt.

The interrupt source (like an external pin) must be configured to trigger the ISR and wake the device.

c
#include <avr/sleep.h>
#include <avr/interrupt.h>

// Enable sleep mode
sleep_enable();

// Enable global interrupts
sei();

// Enter sleep mode
sleep_cpu();

// Interrupt Service Routine example
ISR(INT0_vect) {
    // Code to run on interrupt wake-up
}
💻

Example

This example shows how to put an AVR microcontroller to sleep and wake it up using an external interrupt on INT0 (pin PD2). When the button connected to INT0 is pressed, the MCU wakes up and toggles an LED.

c
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>

volatile uint8_t woke_up = 0;

ISR(INT0_vect) {
    woke_up = 1; // Set flag to indicate wake-up
}

int main(void) {
    DDRD &= ~(1 << PD2); // Set PD2 (INT0) as input
    PORTD |= (1 << PD2);  // Enable pull-up on PD2

    DDRB |= (1 << PB0);   // Set PB0 as output (LED)

    // Configure INT0 to trigger on falling edge
    EICRA |= (1 << ISC01);
    EICRA &= ~(1 << ISC00);

    EIMSK |= (1 << INT0); // Enable INT0 interrupt

    sei(); // Enable global interrupts

    while (1) {
        woke_up = 0;

        sleep_enable();
        sleep_cpu(); // Enter sleep mode
        sleep_disable();

        if (woke_up) {
            PORTB ^= (1 << PB0); // Toggle LED on wake-up
        }
    }

    return 0;
}
⚠️

Common Pitfalls

Common mistakes when using interrupts to wake from sleep mode include:

  • Not enabling global interrupts with sei(), so the interrupt never triggers.
  • Forgetting to configure the interrupt trigger correctly (e.g., wrong edge or level).
  • Not clearing or disabling sleep mode after wake-up, causing the MCU to immediately go back to sleep.
  • Using sleep_mode() instead of sleep_cpu() in some environments, which may not put the MCU to sleep properly.
c
// Wrong: Interrupts disabled, MCU never wakes
cli(); // disables interrupts
sleep_enable();
sleep_cpu();
// MCU stays asleep forever

// Correct:
sei(); // enable interrupts
sleep_enable();
sleep_cpu();
sleep_disable();
📊

Quick Reference

Function/InstructionPurpose
sleep_enable()Prepare MCU to enter sleep mode
sleep_cpu()Put MCU into sleep mode until interrupt occurs
sleep_disable()Disable sleep mode after wake-up
sei()Enable global interrupts
cli()Disable global interrupts
ISR(vector)Interrupt service routine to handle wake-up event

Key Takeaways

Enable global interrupts with sei() before entering sleep mode to allow wake-up.
Configure the interrupt source correctly to trigger the wake-up event.
Use sleep_enable() and sleep_cpu() to enter sleep mode and sleep_disable() after waking.
Write an ISR to handle the interrupt and perform actions after wake-up.
Common errors include forgetting to enable interrupts or misconfiguring the interrupt trigger.