This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

MSP430FR2433: I need a review to achieve less current consumption.

Part Number: MSP430FR2433
Other Parts Discussed in Thread: ENERGYTRACE

Hi,

I interfaced proximity sensor vcnl4010. But my requirement is to reduce the current consumption. I'm supplying 3.3v externally from TPS715345 LDO where quiescent current is around 4.8uA. But my problem is i'm not achieving that current instead i'm getting 135uA. Before going to sleep i'm stopping supply to sensor also. Here is my code. Can anyone look into that and give me an idea to achieve low current consumption in the range of 5uA ?

Thankyou,

Manideep

#include "driverlib.h"
#include <msp430.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <math.h>

#define INTERVAL_TIME   58600
#define CR              13
#define LF              10
#define UART_TIMEOUT    9876
#define SLAVE_ADDRESS   0x13
#define CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ   1000
#define CS_SMCLK_FLLREF_RATIO               30

uint8_t TXData=0;
uint8_t RXData=0;
uint8_t reg;
uint32_t result;
uint32_t result1;
uint16_t ID;
uint16_t distance;
unsigned int i;
unsigned int timerflag=0;
unsigned int delayflag=0;
unsigned int Interrupt=0;
char debug_string [123];

void RTC_Int(void);
void uart_init(void);
bool uart_send_debug_string(char []);
bool uart_send_byte(char);
void I2C_init(void);
void clk_init(void);
void LED_Blink(void);
void Transmit(uint8_t);
void Receive(void);
void command_enable(uint8_t,uint8_t);
void Timer_Delay_Init();

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;     // Stop WDT
  PM5CTL0 &= ~LOCKLPM5;
  clk_init();                   // Clock Source Initialization
  uart_init();                  // UART Initialization
  RTC_Int();                    // RTC Initialization to wake mcu every 1 minute
  TA0CCR0 = 12500;              // timer counter to blink led for 100ms
  __bis_SR_register(GIE);
  while(1)
  {
     GPIO_setAsOutputPin(GPIO_PORT_P2,GPIO_PIN1);
     GPIO_setOutputHighOnPin(GPIO_PORT_P2,GPIO_PIN1);
     I2C_init();                   // I2C Initialization
     LED_Blink();

     command_enable(0x80 , 0xFF);  // Enabling the Range Bit for Measurement
     command_enable(0x82 , 0x00);  // Measuring 1.95 Measurements per Second
     command_enable(0x83 , 0x10);  // LED Current Set to 100mA

     Timer_Delay_Init();
     while(delayflag==0);
     delayflag=0;
     Timer_A_stop(TIMER_A1_BASE);
     Timer_A_clear(TIMER_A1_BASE);

     for(i=10;i>0;i--)
     {
          Transmit(0x87);      // Transmitting MSB Range bit
          Receive();           // Receiving MSB Range data
          result = RXData;
          result = (result<<8);
          RXData = 0;          // Clearing Received data

          Transmit(0x88);      // Transmitting LSB Range bit
          Receive();           // Receiving LSB Range data
          result1 = RXData;
          result |= result1;   // Adding LSB bit to MSB
          RXData = 0;          // clearing Received data

          distance = exp(log(136000 / result) / 1.765);
          sprintf(debug_string,"Distance(cm): %d", distance);
          uart_send_debug_string(debug_string);     // Displaying Range data
      }
      GPIO_setOutputLowOnPin(GPIO_PORT_P2,GPIO_PIN1);
      __bis_SR_register(LPM4_bits);           // Enter LPM3 interrupt
  }
}

void Timer_Delay_Init()
{

        //Start timer in continuous mode sourced by ACLK
        Timer_A_clearTimerInterrupt(TIMER_A1_BASE);

        Timer_A_initContinuousModeParam param = {0};
        param.clockSource = TIMER_A_CLOCKSOURCE_SMCLK;
        param.clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_16;
        param.timerInterruptEnable_TAIE = TIMER_A_TAIE_INTERRUPT_ENABLE;
        param.timerClear = TIMER_A_DO_CLEAR;
        param.startTimer = true;
        Timer_A_initContinuousMode(TIMER_A1_BASE, &param);
}

void RTC_Int()
{
        //Initialize RTC
        RTC_init(RTC_BASE,INTERVAL_TIME,RTC_CLOCKPREDIVIDER_1024);

        RTC_clearInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT_FLAG);

        //Enable interrupt for RTC overflow
        RTC_enableInterrupt(RTC_BASE,RTC_OVERFLOW_INTERRUPT);

        //Start RTC Clock with clock source SMCLK
        RTC_start(RTC_BASE, RTC_CLOCKSOURCE_SMCLK);
}

void I2C_init()
{
        // Configure Pins for I2C
        GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1,GPIO_PIN2 + GPIO_PIN3,GPIO_PRIMARY_MODULE_FUNCTION);

        // Configuring the Master
        EUSCI_B_I2C_initMasterParam param = {0};
        param.selectClockSource = EUSCI_B_I2C_CLOCKSOURCE_SMCLK;
        param.i2cClk = CS_getSMCLK();
        param.dataRate = EUSCI_B_I2C_SET_DATA_RATE_400KBPS;
        EUSCI_B_I2C_initMaster(EUSCI_B0_BASE, &param);
}
void Transmit(uint8_t reg)
{
       //Specify slave address
       EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);

       //Set Master in Transmit mode
       EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_MODE);

       //Enable I2C Module to start operations
       EUSCI_B_I2C_enable(EUSCI_B0_BASE);

       EUSCI_B_I2C_clearInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_INTERRUPT0) ;
       //Enable master transmit interrupt
       EUSCI_B_I2C_enableInterrupt(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_INTERRUPT0);

       TXData = reg;
       EUSCI_B_I2C_masterSendSingleByte(EUSCI_B0_BASE, TXData);
}

void Receive(void)
{
        //Specify slave address
        EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);

        //Set Master in receive mode
        EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_RECEIVE_MODE);

        // I2C start condition
        RXData = EUSCI_B_I2C_masterReceiveSingleByte(EUSCI_B0_BASE);
}

void command_enable(uint8_t command,uint8_t data)
{
    //Specify slave address
    EUSCI_B_I2C_setSlaveAddress(EUSCI_B0_BASE,SLAVE_ADDRESS);

    //Set Master in Transmit mode
    EUSCI_B_I2C_setMode(EUSCI_B0_BASE,EUSCI_B_I2C_TRANSMIT_MODE);

    //Enable I2C Module to start operations
    EUSCI_B_I2C_enable(EUSCI_B0_BASE);

    EUSCI_B_I2C_masterSendMultiByteStart(EUSCI_B0_BASE, command);
    EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE,command);
    EUSCI_B_I2C_slavePutData(EUSCI_B0_BASE,data);

    EUSCI_B_I2C_masterSendMultiByteStop(EUSCI_B0_BASE);
   }



void LED_Blink(void)
{
    if(Interrupt==1)
          {
              TA0CTL |= TACLR;                              // Clearing timerA Register
              P1DIR |= BIT0;
              P1OUT |= BIT0;                                // LED is turned ON
              TA0CCTL0 |= CCIE;                             // TACCR0 interrupt enabled
              TA0CTL |= TASSEL__SMCLK | ID_3 | MC__UP ;     // SMCLK, continuous mode
              while(timerflag==0);
              timerflag=0;
              P1OUT &= ~BIT0;                               // LED is turned OFF
              TA0CCTL0 &= ~CCIE;                            // TACCR0 interrupt Disabled
              TA0CTL &= ~MC__UP;
          }
}

void uart_init (void)
{
    // Configure UART pins
    P1SEL0 |= BIT4 | BIT5;          // set 2-UART pin as second function

    // Configure UART
    UCA0CTLW0 |= UCSWRST;           // Put eUSCI in reset
    UCA0CTLW0 |= UCSSEL__SMCLK;     // Chose SMCLK as clock source

    // Baud Rate calculation for 9600 with SMCLK (1MHz)
    // 1000000/9600 = 104.16
    // 1000000/9600 - INT(1000000/9600)=0.16
    // UCBRSx value = 0x11 (See UG)
    UCA0BR0 = 104;
    UCA0MCTLW = 0x1100;
    UCA0BR1 = 0;
    UCA0CTLW0 &= ~UCSWRST;          // Initialize eUSCI
}

bool uart_send_byte (char data)
{
    uint16_t uart_timeout = UART_TIMEOUT;   // load time out value

    while((!(UCA0IFG & UCTXIFG))&&(uart_timeout>0))
    {
        uart_timeout--;                     //  wait till TX interrupt pending
    }

    if(uart_timeout == 0)
    {
        return false;                       // failure if time out
    }

    UCA0TXBUF = data;
    return true;                            // success otherwise

}

bool uart_send_debug_string (char array[])
{
    uint16_t size = strlen(array);
    uint16_t index = 0;

    for(index=0; index<size; index++)
    {
        if(!uart_send_byte(array[index]))   // send char one by one
        {
            return false;
        }
    }

    if(!uart_send_byte(CR))                 // send carriage return
    {
        return false;
    }

    if(!uart_send_byte(LF))                 // send line feed for new line
    {
        return false;
    }

    return true;
}
void clk_init(void)
{

    // Set Ratio and Desired MCLK Frequency  and initialize DCO
    CS_initFLLSettle(CS_SMCLK_DESIRED_FREQUENCY_IN_KHZ,CS_SMCLK_FLLREF_RATIO);

    // Set SMCLK = DCO with frequency divider of 1
    CS_initClockSignal(CS_SMCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);

    CS_initClockSignal(CS_MCLK,CS_DCOCLKDIV_SELECT,CS_CLOCK_DIVIDER_1);

    P1OUT |= BIT1 + BIT2 + BIT4 + BIT5 + BIT3 + BIT7  ;
    P1DIR |= BIT1 + BIT2 + BIT4 + BIT5 + BIT3 + BIT7  ;
    P2OUT |= BIT0 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7  + BIT3 ;
    P2DIR |= BIT0 + BIT2 + BIT4 + BIT5 + BIT6 + BIT7  + BIT3 ;
}


#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(RTC_VECTOR)))
#endif
void RTC_ISR (void)
{
    switch (__even_in_range(RTCIV,2)){
        case 0: break;  //No interrupts
        case 2:         //RTC overflow
            Interrupt=1;
            __low_power_mode_off_on_exit();
            break;
        default: break;
    }
}


// Timer A0 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = TIMER0_A0_VECTOR
__interrupt void Timer_A0 (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(TIMER0_A0_VECTOR))) Timer_A0 (void)
#else
#error Compiler not supported!
#endif
{
    timerflag=1;
}

//******************************************************************************
//
//This is the TIMER1_A3 interrupt vector service routine.
//
//******************************************************************************
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=TIMER1_A1_VECTOR
__interrupt
#elif defined(__GNUC__)
__attribute__((interrupt(TIMER1_A1_VECTOR)))
#endif
void TIMER1_A1_ISR (void)
{
    //Any access, read or write, of the TAIV register automatically resets the
    //highest "pending" interrupt flag
    switch ( __even_in_range(TA1IV,14) ){
        case  0: break;                          //No interrupt
        case  2: break;                          //CCR1 not used
        case  4: break;                          //CCR2 not used
        case  6: break;                          //CCR3 not used
        case  8: break;                          //CCR4 not used
        case 10: break;                          //CCR5 not used
        case 12: break;                          //CCR6 not used
        case 14:

            delayflag=1;

            break;
        default: break;
    }
}

  • Hi maanideep kumar,

    It seems CPU is in LPM0 rather than LPM3. Because there are peripherals request SMCLK which prevent system getting into LPM3. Try to use ACLK for RTC.

    Ling

  • I would suggest to use EnergyTrace for getting power profiles of the code execution.

    Best regards
    Lukas
  • Hi,

    For ACLK which clock source do I need to use REFOCLK or XTLCLK ?

    Thank you ,

    Manideep

  • Why not REFOCLK???
  • Because power consumption of REFOCLK is 10+uA more than XT1. Please refer to device datasheet.

  • Hi Ling,

    I just want to try  ACLK with clock source REFOCLK. But the RTC is not triggering. Here is the code i took it from ti driver lib examples. Just changed  from SMCLK to ACLK.

    Thankyou,

    Manideep  

    #include "driverlib.h"
    #include "Board.h"
    
    //*****************************************************************************
    //
    //Interval time used for RTC
    //
    //*****************************************************************************
    #define INTERVAL_TIME 32768
    
    void main (void)
    {
        WDT_A_hold(WDT_A_BASE);
    
        //Set LED1 to output direction
    
    
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
    
        //Set DCO FLL reference = REFO
        /*CS_initClockSignal(
            CS_FLLREF,
            CS_REFOCLK_SELECT,
            CS_CLOCK_DIVIDER_1
            );*/
    
        //Set ACLK = REFO
        CS_initClockSignal(
            CS_ACLK,
            CS_REFOCLK_SELECT,
            CS_CLOCK_DIVIDER_1
            );
    
        //Initialize RTC
        RTC_init(RTC_BASE,
            INTERVAL_TIME,
            RTC_CLOCKPREDIVIDER_1);
    
        RTC_clearInterrupt(RTC_BASE,
            RTC_OVERFLOW_INTERRUPT_FLAG);
    
        //Enable interrupt for RTC overflow
        RTC_enableInterrupt(RTC_BASE,
            RTC_OVERFLOW_INTERRUPT);
    
        //Start RTC Clock with clock source ACLK
        RTC_start(RTC_BASE, RTC_CLOCKSOURCE_ACLK);
    
        //Enter LPM3 mode with interrupts enabled
        __bis_SR_register(LPM0_bits + GIE);
        __no_operation();
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(RTC_VECTOR)))
    #endif
    void RTC_ISR (void)
    {
        switch (__even_in_range(RTCIV,2)){
            case 0: break;  //No interrupts
            case 2:         //RTC overflow
                GPIO_setAsOutputPin(
                        GPIO_PORT_LED1,
                        GPIO_PIN_LED1
                        );
                //Toggle LED1
                GPIO_toggleOutputOnPin(
                GPIO_PORT_LED1,
                GPIO_PIN_LED1);
                break;
            default: break;
        }
    }
    

  • Hi,

    Please try the code example:

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2017, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    //******************************************************************************
    //!
    //! RTC in Counter Mode toggles LED1 every 1s
    //!
    //!  This program demonstrates RTC in counter mode configured to source from SMCLK
    //!  to toggle LED1 every 1s.
    //!  SMCLK = REFO = ~32kHz
    //!
    //!           MSP430FR2xx_4xx Board
    //!             -----------------
    //!        /|\ |                 |
    //!         |  |                 |
    //!         ---|RST              |
    //!            |                 |
    //!            |                 |-->LED1
    //!
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - RTC peripheral
    //! - GPIO Port peripheral
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - RTC_VECTOR
    //!
    //******************************************************************************
    #include "driverlib.h"
    #include "Board.h"
    
    //*****************************************************************************
    //
    //Interval time used for RTC
    //
    //*****************************************************************************
    #define INTERVAL_TIME 32768
    
    void main (void)
    {
        WDT_A_hold(WDT_A_BASE);
    
        //Set LED1 to output direction
        GPIO_setAsOutputPin(
            GPIO_PORT_LED1,
            GPIO_PIN_LED1
            );
    
        /*
         * Disable the GPIO power-on default high-impedance mode to activate
         * previously configured port settings
         */
        PMM_unlockLPM5();
    
        //Set DCO FLL reference = REFO
        CS_initClockSignal(
            CS_FLLREF,
            CS_REFOCLK_SELECT,
            CS_CLOCK_DIVIDER_1
            );
    
        //Set SMCLK = REFO
        CS_initClockSignal(
            CS_SMCLK,
            CS_REFOCLK_SELECT,
            CS_CLOCK_DIVIDER_1
            );
    
        //Initialize RTC
        RTC_init(RTC_BASE,
            INTERVAL_TIME,
            RTC_CLOCKPREDIVIDER_1);
    
        RTC_clearInterrupt(RTC_BASE,
            RTC_OVERFLOW_INTERRUPT_FLAG);
    
        //Enable interrupt for RTC overflow
        RTC_enableInterrupt(RTC_BASE,
            RTC_OVERFLOW_INTERRUPT);
    
        //Start RTC Clock with clock source SMCLK
        RTC_start(RTC_BASE, RTC_CLOCKSOURCE_SMCLK);
    
        //Enter LPM3 mode with interrupts enabled
        __bis_SR_register(LPM0_bits + GIE);
        __no_operation();
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=RTC_VECTOR
    __interrupt
    #elif defined(__GNUC__)
    __attribute__((interrupt(RTC_VECTOR)))
    #endif
    void RTC_ISR (void)
    {
        switch (__even_in_range(RTCIV,2)){
            case 0: break;  //No interrupts
            case 2:         //RTC overflow
                //Toggle LED1
                GPIO_toggleOutputOnPin(
                GPIO_PORT_LED1,
                GPIO_PIN_LED1);
                break;
            default: break;
        }
    }
    

    Ling

  • Yes, but this is for SMCLK but I need ACLK.
  • Hi maanideep kumar,

    This device doesn't support ACLK clock to RTC. Please refer to datasheet.

    Ling

**Attention** This is a public forum