3.1.12
Using Power-Down Mode
Again, our power consumption has been reduced but the CPU is still in a “lighter” Sleep mode than it needs to be. To
go into Power-Down mode we have to switch to the Watchdog Timer as a wake-up source. When the watchdog
wakes and triggers an interrupt, we light the LED and go into IDLE mode until we switch it off again. The code below
is included in project low_power_104.
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/power.h>
#include <avr/wdt.h>
volatile
uint8_t
deep_sleep = 0;
ISR (WDT_vect)
{
// LED is OFF, turn it on
PORTB = (1 << 5);
// Flag a lighter sleep state
deep_sleep = 0;
}
ISR (TIMER2_OVF_vect)
{
// LED is ON, turn it off
PORTB = 0x00;
// Flag a deep-sleep state
deep_sleep = 1;
}
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 and 2 modules
power_timer0_disable();
// Timer 2 needs to stay on
//power_timer2_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);
// Watchdog reset
wdt_reset();
// Start timed sequence
WDTCSR |= (1<<WDCE) | (1<<WDE);
// Set new prescaler(time-out) value = 64K cycles (~0.5s)
WDTCSR = (1<<WDIE) | (1<<WDP2) | (1<<WDP1);
Power Debugger
Detailed Use Cases
©
2020 Microchip Technology Inc.
User Guide
DS40002201A-page 22