Using Sleep Mode

Power consumption has been reduced, but the CPU is still actively doing nothing. To benefit from an interrupt-driven model, the CPU can be put to sleep while waiting for interrupts. In addition we will power down all peripherals not used to further reduce power consumption. The code below is included in project low_power_103.

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

ISR (TIMER2_OVF_vect)
{
    if (PORTB == 0x00) {
        // LED is OFF, turn it on
        PORTB = (1 << 5);
        // Shortened timeout for on cycle
        TCNT2 = 0x102;
    }
    else {
        // LED is ON, turn it off
        PORTB = 0x00;
    }
}

int main(void)
{
    // Disable digital input buffer on ADC pins
    DIDR0 = (1 << ADC5D) | (1 << ADC4D) | (1 << ADC3D)
    | (1 << ADC2D) | (1 << ADC1D) | (1 << ADC0D);
    // Disable digital input buffer on Analog comparator pins
    DIDR1 |= (1 << AIN1D) | (1 << AIN0D);
    // Disable Analog Comparator interrupt
    ACSR &= ~(1 << ACIE);
    // Disable Analog Comparator
    ACSR |= (1 << ACD);
    // Disable unused peripherals to save power
    // Disable ADC (ADC must be disabled before shutdown)
    ADCSRA &= ~(1 << ADEN);
    // Shut down the ADC
    power_adc_disable();
    // Disable SPI 
    power_spi_disable();
    // Disable TWI
    power_twi_disable();
    // Disable the USART 0 module
    power_usart0_disable();
    // Disable the Timer 1 module
    power_timer1_disable();
    // Disable the Timer 0 module
    power_timer0_disable();

    // Change the clock prescaler
    CLKPR = (1 << CLKPCE);
    // Scale by DIV64
    CLKPR = (1 << CLKPS2) | (1 << CLKPS1) | (0 << CLKPS0);
    // Port B5 to output
    DDRB = (1 << 5);
    // Timer2 DIV 1024 
    TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20); 
    // Overflow interrupt enable
    TIMSK2 = (1 << TOIE2); 
    // Interrupts on
    sei();
    while (1) {
        set_sleep_mode(SLEEP_MODE_PWR_SAVE);
        sleep_mode();
    }	
}
Todo:
  • Build the project/solution (F7)
  • Program the application into the target device using Start Without Debugging (Ctrl+Alt+F5)
  • Switch to Data Visualizer to see the results
Important: Because the previous example prescaled the clock to 8MHz/64, the ISP programming clock must be set to less than 32kHz to be below 1/4 of the main clock.
Important: Remember to disable on-board power on the Xplained Mini.
What can we see from this plot?
Result: Power consumption has again been improved by using sleep mode and disabling unused peripherals.