RTC en el microcontrolador MSP430 con cristal de 32.768 kHz y baja potencia

0

Necesito configurar el temporizador para interrumpir cada segundo. Estoy usando un cristal externo de 32.768 kHz con MCU MSP430G2553. La configuración debería consumir < 10μA.

Probé este código pero consumió 80-90 μA. ¿Qué estoy haciendo mal?

¿Por qué el consumo es demasiado alto?

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)
{
}
    
pregunta maradono

1 respuesta

1

Podría haber varias razones: ¿está funcionando el oscilador de cristal? No veo su programa configurando el puerto 2 para habilitarlo.

Aquí hay un ejemplo del programa "Blinky" cuyo consumo de corriente se ha medido en 1 uA (¡sin LED!). Una versión más compleja que implementa un reloj digital LED de estilo de los años 70 se ejecuta en el 2553, nuevamente bajo 1 uA (pantalla apagada) en menos de un kilobyte.

No está en C, pero creo que es bastante fácil de leer, y es posible que encuentres la configuración que necesitas en los procedimientos Init_Clock o Start_Delay.

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; 

Utiliza un paquete "Timer_X" para manejar los detalles de bajo nivel de configuración del oscilador y el temporizador: la especificación del paquete es

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;

y el cuerpo del paquete (implementación) es

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;
    
respondido por el Brian Drummond

Lea otras preguntas en las etiquetas