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.

MSP430g2553 LaunchPad wake up from Low Power Mode

Other Parts Discussed in Thread: MSP430G2553

Hello there,

I want to try a little programm from Aldo Briano, here is the wiki link:
processors.wiki.ti.com/.../MSP430_LaunchPad_Low_Power_Mode.
Programm goes in low power mode (CPUOFF and GIE in status register are 1),
but I cannot wake up the CPU by pressing P1.3 button.
I have launchpad  MSP-EXP430G2  with MSP430G2553 Rev. 1.5, there is no crystal soldered and Pullup resistor R34 and capacitor C24 on P1.3 are removed. I work with CCS  Version: 6.2.0.00050.

I am using VLOCLK and ACLK for energy saving. I think it doesn´t matter witch low power mode I am selecting. Code should work with any mode.

Here is the code:

//******************************************************************************
// MSP430G2xx Demo - WDT, Low Power Mode, Interval Overflow ISR, DCO SMCLK
//
// Description: Go to LowPowerMode using software timed by the WDT ISR. The LED
// will turn off when sleeping, Port 1 interrupt will awake the mcu and turn on
// LED. The mcu will sleep at approximately 250 * 32ms based on default
// DCO/SMCLK clock source used in this example for the WDT.
// ACLK = n/a, MCLK = SMCLK = default
//
// MSP430G2xxx
// -----------------
// /|\| XIN|-
// | | |
// --|RST XOUT|-
// | |
// | P1.0|-->LED
//
// Aldo Briano
// Texas Instruments Inc.
// July 2010
//******************************************************************************
#include <msp430g2553.h>



unsigned int wdtCounter = 0;
void main(void)
{
WDTCTL = WDT_MDLY_32; // Set Watchdog Timer interval to ~32ms
IE1 |= WDTIE; // Enable WDT interrupt
P1DIR |= BIT0;// Set P1.0 to output direction
P1OUT |= BIT0; // Turn on LED at 1.0
P1REN |= BIT3;// Enable resistor on SW2 (P1.3)
P1DIR |= BIT3;// Set P1.3 to output direction to prevent floating

P1OUT |= BIT3; // Enable Pull Up on SW2 (P1.3)
P1IE |= BIT3; // enable P1.3 interrupt
//P1IES |= BIT3;

BCSCTL3 =LFXT1S_2;   // run ACLK from VLO
__enable_interrupt();

for(;;)
{

}
}

// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
#pragma INTERRUPT(watchdog_timer)
void watchdog_timer(void)
{
if(wdtCounter == 249)
{
P1OUT = 0x00; // P1.0 turn off
wdtCounter = 0;
__bis_SR_register(LPM0_bits + GIE); // Enter LPM w/interrupt
}
else
{
wdtCounter++;
}

}
// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
#pragma INTERRUPT (Port_1)
void Port_1(void)
{
wdtCounter = 0; // reset watchdog timer counter
P1OUT |= 0x01; // turn LED on
P1IFG = 0x0;
__bic_SR_register_on_exit(LPM0_bits); // wake up from low power mode

}

  • > P1OUT = 0x00; // P1.0 turn off

    This turns the P1.3 (internal) pullup into a pulldown. In the absence of the external resistor, you rely on the internal one. Try:

    > P1OUT &= ~0x01; // P1.0 turn off
  • Oh, and I missed this:
    > P1DIR |= BIT3;// Set P1.3 to output direction to prevent floating
    The button input should be input, not output. The internal pullup will keep it from floating.
    Just remove this line.

    Also, my arithmetic says that the button won't really be effective for about 249*32ms=8 seconds, so don't be impatient.
  • Dear Bruce,

    great job, thank you very much, I corrected my code like you told me, and its working fine now!

    First, the user guide tells at 2.1.2 after system start all pins are switched to input mode and with my code I would enable pulldown resistors on all pins (user guide at 8.2.2). So like you told me I only should switch pin 0 to zero and leave the other pins at 1 concerning the output register.

    Second, you are right, the user guide tells at 8.2.8 that enabling the resistor prevents from floating and it makes no sence to set P1.3 to output because the microcontroller should read if the button is pushed or not and therefor it must be configured as input.

    What do you mean with your last sentence:
    Also, my arithmetic says that the button won't really be effective for about 249*32ms=8 seconds, so don't be impatient.
    I just have to push the button short and the red led will light again for about 8 sec, I dont need to push and hold the button for 8 seconds.

    Yours Elmar
  • All I meant is that as near as I can tell the program doesn't sleep for the first 8 seconds, so if you push the button immediately you aren't really waking anything up. All the P1.0 LED tells you (actually) is that you pushed the button.

    Perhaps a more interesting display would be to (1) turn the LED on at the top of main (2) turn off the LED just before the "__bis_SR_register(LPM0_bits + GIE); " statement [as it does now] and (3) turn it back on immediately after that statement, rather than in Port_1(). That way the LED reflects the LPM state.

    I followed that link you provided, and didn't find anything (at all?) there, so I don't really know what the intent was for this program; I'm just reading what the code you posted says.

    Unsolicited: I don't recommend the technique of going into (enabled) LPM0 in an ISR, since it invites a stack overflow -- if you stop pushing the button, I estimate this program will last about 4 minutes before it crashes.

    [Edit: I just noticed you were doing (1) already.]

  • You are right, the link is not working.
    Please try this link, I hope its working:

    processors.wiki.ti.com/.../MSP430_LaunchPad_Low_Power_Mode

    I tried your suggestions in my program an its also working fine. The program is working, there is no crash. I am new to microcontroller, so I dont know about the stack overflow.
    The intention of the program is to put the controller to sleep while I am programming and just wake it up when I want by pushing the button to see if a new program is running as expected.
    I have a program running an OLED-Display and I dont want to run the display for hours while I am programming.
    At the moment I want to include the low power code into the OLED-Project, but I am still trying and I see it is not easy.
  • please replace the three dots" ..." with "index.php"
  • If you're just starting out, I suggest you not use this program as a model. It's quite cute and succinct, but teaches some habits that really don't scale to a significant application.

    Most notably, you shouldn't go into LPM (which requires re-enabling interrupts) in an ISR, for a couple of reasons: (1) recursive interrupts leading to stack overflow [as mentioned] (2) You never know when it will happen -- main could be in the middle of doing something important. This program gets away with it since it "knows" that main is never doing anything.

    Generally, you should only go into LPM in main, and only when you know that there is some event (interrupt) which will wake you up. The ISR should wake up main as needed, which can then decide what (if anything) needs to be done.

    More generally: The flow of control is quite scattered; this is workable in a 40-line program but rapidly becomes hard to follow as the program grows. main should be making the decisions, with the ISRs supplying information.

    Also, using the WDT as an interval timer is perfectly valid, but it also means you can't use it as an actual Watchdog.

    One illustration of the more "standard" model is in the MSP430G2553 Examples (SLAC485D, product page "Tools and Software"): msp430g2xx3_lpm3.c. (It also uses the WDT as an interval timer.)

**Attention** This is a public forum