Post comments on this article and find any associated files and/or downloads at
if( restart_cause() == NORMAL_POWER_UP )
This essentially asks, “What woke me up?”
CCS PIC® C Compiler
There can be several reasons for a processor waking
up; the two we are concerned with are NORMAL_
Microchip Low Power
Design Guide is a bit more
POWER_UP and RESET_INSTRUCTION. When we connect
the battery for the first time or replace the batteries, the
processor wakes up and detects a NORMAL_POWER_UP
as the reason. The code then tells it to go to sleep since
we only want it to turn on after a reset that was initiated
by a button press.
David Jones' µCurrent
current adapter for
The function HWSleep() prepares the processor for
the lowest possible power consumption, sets up the
interrupt, and puts the processor to sleep:
David Jones Video Blog —
Microchip Tips & Tricks
Guide; Section 2 addresses
low power issues
Adafruit µCurrent listing —
an excellent short
void HWSleep( void )
//— power down what we can...
setup_adc_ports( NO_ANALOGS );
setup_vref( VREF_OFF ); // uses 16uA when on
setup_timer_1( T1_DISABLED );
// turn off timers
setup_timer_2( T2_DISABLED );
output_a( 0x00 ); // turn off everything
output_high( PFET );
// set high to turn off pFET
enable_interrupts( INT_RA4_L2H );
// turn on interrupt on power button
sleep(); // go to sleep
processor: 1) the low power sleep mode; and 2) a “wake
on interrupt” which can come from a voltage change on
any of the I/O pins. These features can be found on
microprocessors from many different manufacturers (not
just those from Microchip). Starting from sleep mode, the
general operation is as follows:
// Wakeup from sleep resumes here...
clear_interrupt( INT_RA4_L2H );
// clean up interrupt from sleep
disable_interrupts( INT_RA4_L2H );
// do a full reset when we wake up
1. The user presses the power button.
All the instructions up to enable_interrupts() are
designed to eliminate any current leakage through the
processor, and to turn off power to peripheral devices.
2. The processor detects the change from low to high
on a pin and wakes up.
3. The processor goes on to initialize itself and
The specific instructions will depend on the internal and
external peripherals, special features of the processor, and
so on. The spec sheet has all the information you need.
continues to perform its main task which, in this
case, is to turn on an LED.
4. The main processing loop checks for a button press
However, you may need help from user forums and other
documentation to make sense of it, and some of it is just
trial and error.
of a certain length of time (two seconds, in this
case). This can be with the same button that turned
the system on.
5. Once that button press has been detected, the
processor turns off all peripherals, sets up the
conditions to detect the next “power on” event,
and goes to sleep.
For example, I had a serial connection I was using for
debugging, and I just couldn’t get the current draw near to
what I was expecting. Once I disconnected the serial
cable, all was fine. So, for those applications that have a
serial connection built in, you need to add additional
commands to be sure it doesn’t draw power from the
processor during sleep mode.
Let’s look a little closer at how this happens.
The system doesn’t start out in sleep mode. When it
first gets turned on (for example, when we put in new
batteries), we don’t want it to interpret this as a start
signal. Fortunately, the processor can determine how it
The enable_interrupts() instruction tells the system
which pin will be used to wake it up, and the next
instruction puts it to sleep. When the selected pin detects
a change (in this case, a transition from low to high), the
processor wakes up and resumes processing from the
point at which it went to sleep.
One of the first commands executed after startup is:
Then, we clean up our interrupt handling and force a
restart of the processor, so it can start fresh by going
42 November 2014