0
\$\begingroup\$

I need to set timer to interrupt every second. I'm using 32.768kHz external crystal with MSP430G2553 MCU. The setup should consume < 10μA.

I tried this code but it consumed 80-90 μA. What am I doing wrong?

Why is consumption too high?

int main(void) {
  WDTCTL = WDTPW | WDTHOLD;

  BCSCTL1 |= DIVA_3;    // divide by 8
  BCSCTL3 |= XCAP_3;

  //set timer
  TA1CCTL0 = CM_0 + CCIS_0 + OUTMOD_0 + CCIE;
  TA1CCR0 = 1020;
  TA1CTL = TASSEL_1 + ID_2 + MC_1;

  LPM3;
}

//interupt every 1000ms
#pragma vector=TIMER1_A0_VECTOR
__interrupt void TIMER1_A0_ISR(void)
{
}
\$\endgroup\$
1
  • 1
    \$\begingroup\$ How are you measuring the current? Do you have the programmer lines connected? Make sure unused I/O lines are tied up/down by hardware or software -- easiest is to use REN to enable internal pullup/down resistors. \$\endgroup\$
    – markrages
    May 6, 2013 at 2:59

1 Answer 1

2
\$\begingroup\$

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;
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.