A lot isn't explained in the chip's own datasheet. With 450 processor models, this makes perfect sense : the datasheet describes the chip-specific stuff; common information is refactored out into a user manual covering the entire family of devices.
The user manual for that device family is
MSP430x2xx Family User's Guide
Literature Number: SLAU144J
Operating modes, ch 2.3, p.38 says:
When setting any of the mode-control bits, the selected operating mode takes effect immediately (see
Figure 2-9). Peripherals operating with any disabled clock are disabled until the clock becomes active. The
peripherals may also be disabled with their individual control register settings. All I/O port pins and
RAM/registers are unchanged. Wake up is possible through all enabled interrupts.
So, the I/O pins retain their current function and (for output pins) values.
In other words if you're trying to save power, any power they are supplying to LEDs etc is your problem (turn them off, along with peripherals you don't need, before sleeping).
Could be a number of reasons : is the crystal oscillator working? I don't see your program setting port 2 up to enable it.
Here is an example "Blinky" program whose current consumption has been measured under 1 uA (with no LED!). A more complex version implementing a 1970's style LED digital watch runs on the 2553, again under 1 uA (display off!) in under a kilobyte.
It's not in C but I think it's pretty easy to read, and you may find settings you need in the Init_Clock or Start_Delay procedures.
with Interfaces; use Interfaces;
with CPU;
with timer_X;
procedure Blinky_xtal is
-- This example demonstrates a very small Ada application built
-- using gcc-msp intrinsic functions (for delay, manipulating interrupts).
-- New in Blinky_xtal: a 32768Hz crystal oscillator
use CPU.wdt;
use CPU.port1_r;
LED : Boolean renames p1out_bits(0);
begin
-- Initialise registers
wdtctl := wdtpw or wdthold;
p1dir := unsigned_8(CPU.cpu.bit0 or CPU.cpu.bit5);
p1sel := unsigned_8(CPU.cpu.bit5);
timer_X.Init_Clock;
timer_X.Start_Delay_MS(128);
loop
LED := True;
timer_X.Wait;
LED := False;
timer_X.Wait;
end loop;
end Blinky_xtal;
It uses a package "Timer_X" to handle the low level details of setting the oscillator and timer : the package spec is
with CPU;
package timer_X is
procedure Start_Delay_MS(MS : Natural);
procedure Init_Clock;
procedure Wait;
pragma Inline_Always(Wait);
private
procedure Handler;
pragma Machine_Attribute (Entity => Handler,
Attribute_Name => "interrupt",
Info => CPU.vectors.timera0_vector);
end timer_X;
and the package body (implementation) is
with CPU;
with System.GCC_Builtins;
with Interfaces; use Interfaces;
package body timer_X is
use CPU.ta2;
use CPU.bc2;
use CPU.port1_r;
procedure Handler is
begin
-- clear Low Power Mode in status reg copy on stack; loaded on RETI
System.GCC_Builtins.bic_status_register_on_exit(CPU.cpu.lpm3);
end;
procedure Init_Clock is
begin
-- MCLK is 1 MHz DCO
dcoctl := 0; -- slowest setting during setup
-- ClkCtrl 1 Calibration XT2off XTS DIVA
bcsctl1 := CPU.calibration.calbc1_1mhz or xt2off or diva_3;
dcoctl := CPU.calibration.caldco_1mhz;
-- set MClk to 1 MHz.
-- ClkCtrl 2 SELMx DIVMx SELS DIVSx DCOR
-- 0=DCO 0=div1 0=dco 3=div8 0=int
bcsctl2 := selm_0 or divm_0 ;
-- ClkCtrl 3 XT2Sx LFXT1Sx XCAPx XT2OF LFXT1OF
-- 1=6pf fault fault
bcsctl3 := xcap_2;
-- Connect oscillator pins from oscillator to crystal!
-- p2.7 select oscillator, dir=out, p2.6 select osc (dir=in)
p2dir := unsigned_8(CPU.cpu.bit7);
p2sel := unsigned_8(CPU.cpu.bit6 or CPU.cpu.bit7);
-- clear interrupt fault flag
CPU.cpu.ifg1_bits(1) := FALSE;
System.GCC_Builtins.bic_status_register(CPU.cpu.oscoff);
-- and enable interrupts!
System.GCC_Builtins.eint;
end;
procedure Start_Delay_MS(MS : Natural) is
begin
-- set Timer A to interrupt in MS ms
-- Control TASSEL IDx MCx TACLR TAIE TAIFG
-- 2=SMCLK 2=div4 1=ccr clear int+ no flag
ta0ctl := tassel_1 or id_2 or mc_1 or taclr; -- or taie;
-- Capture-Compare Register
ccr0 := Unsigned_16(MS-1);
-- Capture-Compare Control
-- CMx CCISx SCS SCCI CAP OUTMOD CCIE CCI OUT COV CCIFG
-- 0=nocap 0 0 0 0=comp 0 1=int
cctl0 := ccie;
end;
procedure Wait is
begin
-- enter LPM3.
System.GCC_Builtins.bis_status_register(CPU.cpu.lpm3);
end;
end timer_X;
Best Answer
The instruction time is 1/25M = 40ns. Assuming that your interrupt routine is around 20 instructions (it's probably less from the sounds of it), then the routine will last 0.8us.
Assume that the active mode current is drawn for 6us after the ISR has finished, at which point it instantly changes to 2.1uA (for simplification).
In 1ms, the routine will be firing for 6.8us (in active mode) and LPM3 will be on for 993.2us.
If the values you quoted are accurate, then assuming your micro has a 3V supply, 99.32% of the time it will consume 3 x 2.1u = 6.3uW.
For the rest of the time (0.68%), it will consume around 25 x 195u x 3 = 14.6mW.
Since you have the power consumption and the relative times, you can work out the average power.