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 ofsleep_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/Instruction | Purpose |
|---|---|
| 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.