Tinkering TI MSP430F5529

Low Power Modes (LPM) and External Interrupt

At present era, the energy consumption of a device is a very important part of its design. Low power consumption along with optimum performance and long endurance are highly preferable aspects one can think of while crafting a new electronic product. With such in mind, MSP430s were developed with low power consumption feature. In terms of power consumption, MSP430s offer six modes of operation with five being low power or sleep modes of different consumption levels. In TI docs, low power modes are often simply referred as LPMs.

External interrupt is an important DIO input mode feature. It can break the continuity of a regular program flow, i.e. the main routine, and perform certain higher priority secondary tasks separately. Interrupts can be also used to wake up micros from low power sleep modes. Combinations of LPMs and external interrupts have many uses. A good example of such combinations is a wireless mouse. Unless moved or its buttons pressed, the mouse remains in dormant/sleep state to conserve precious battery energy. The internal electronics of the mouse fires up otherwise as if it has been triggered by interrupts caused by motion or button presses. Port A (PA) pins of MSP430F5529 micro are all external interrupt capable pins. Shown below is the structure of a P1 port pin with red regions highlighting external interrupt resources:

Apart from external interrupts, other interrupts like timer interrupts can also wake up a MSP430F5529 from LPM states.

There are 5 LPM modes and an Active Mode of operation. The intent of these modes is to change power consumption by suspending certain hardware and clocks. These are as follows:

• Active mode (AM)

  • All clocks are active.

• Low-power mode 0 (LPM0)

  • CPU and MCLK are disabled.
  • FLL loop control, ACLK and SMCLK remain active.

• Low-power mode 1 (LPM1)

  • CPU, MCLK and FLL loop control are disabled.
  • ACLK and SMCLK remain active.

• Low-power mode 2 (LPM2)

  • CPU, MCLK, FLL loop control and DCOCLK are disabled.
  • DC generator of the DCO remains enabled.
  • ACLK remains active

• Low-power mode 3 (LPM3)

  • CPU, MCLK, FLL loop control, DC generator of the DCO and DCOCLK are disabled.
  • ACLK remains active.

• Low-power mode 4 (LPM4)

  • CPU, ACLK, MCLK, FLL loop control, DC generator of the DCO and DCOCLK are disabled.
  • Crystal oscillator is stopped.
  • Complete data retention.

• Low-power mode 4.5 (LPM4.5)

  • Internal regulator disabled.
  • No data retention.
  • Wake-up signal from RST or NMI, P1, and P2.

Wake up times from various LPM states also varies but these variations are so tiny in terms of time that they are rarely observed visually.

Code Example

#include "driverlib.h"

unsigned char toggle = 0;

void GPIO_init(void);

#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
    LPM3_EXIT;

    if(GPIO_getInterruptStatus(GPIO_PORT_P1,
                               GPIO_PIN1) != 0)
    {
        GPIO_clearInterrupt(GPIO_PORT_P1,
                            GPIO_PIN1);

        toggle = 1;
        _nop();
    }
}

void main(void)
{
    unsigned char i = 0;
    unsigned char j = 0;

    WDT_A_hold(WDT_A_BASE);

    GPIO_init();

    while(1)
    {
        for(j = 0; j < 10; j++)
        {
            GPIO_toggleOutputOnPin(GPIO_PORT_P1,
                                   GPIO_PIN0);

            __delay_cycles(1000000);
        }

        if(toggle)
        {
            for(i = 0; i <= 9; i++)
            {
                GPIO_toggleOutputOnPin(GPIO_PORT_P4,
                                       GPIO_PIN7);

                __delay_cycles(100000);
            }

            toggle = 0;
        }

        LPM3;
    };
}

void GPIO_init(void)
{
    GPIO_setAsOutputPin(GPIO_PORT_P1,
                        GPIO_PIN0);

    GPIO_setDriveStrength(GPIO_PORT_P1,
                          GPIO_PIN0,
                          GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsOutputPin(GPIO_PORT_P4,
                        GPIO_PIN7);

    GPIO_setDriveStrength(GPIO_PORT_P4,
                          GPIO_PIN7,
                          GPIO_FULL_OUTPUT_DRIVE_STRENGTH);

    GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1,
                                         GPIO_PIN1);

    GPIO_clearInterrupt(GPIO_PORT_P1,
                        GPIO_PIN1);

    GPIO_selectInterruptEdge(GPIO_PORT_P1,
                             GPIO_PIN1,
                             GPIO_HIGH_TO_LOW_TRANSITION);

    GPIO_enableInterrupt(GPIO_PORT_P1,
                         GPIO_PIN1);

    __enable_interrupt();
}

Hardware Setup

Explanation

For this demo, on-board P1.1 button, P1.0 and P4.7 LEDs are used. The LEDs are set as in the GPIO example, i.e. as outputs.

P1.1 button pin is set as input pin with pull-up resistor. This pin is also used as the external interrupt pin. At first, any pending interrupt is cleared. We, then, have to set interrupt edge, i.e. polarity sensitivity. Finally, we enable interrupt on the interrupt pin and enable global interrupt.

GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN1);

GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN1);

GPIO_selectInterruptEdge(GPIO_PORT_P1, GPIO_PIN1, GPIO_HIGH_TO_LOW_TRANSITION);

GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN1);

__enable_interrupt();

Now the button pin is ready to behave like an external interrupt pin rather than a regular input pin. Remember that P1 belongs to PA port and only PA port pins are interrupt capable.

Let’s look at the main loop now. Here, we see that P1.0 LED will be toggled 10 times first. The if-condition will not be initially executed since it is linked with the external interrupt. Thus, the conditional statement will be skipped and LPM3 condition will be set.

Once LPM is applied, everything seems to be suspended. P1.0 LED is supposed to keep flashing but that doesn’t happen.

for(j = 0; j < 10; j++)
{
    GPIO_toggleOutputOnPin(GPIO_PORT_P1, GPIO_PIN0);

    __delay_cycles(1000000);
}

if(toggle)
{
    for(i = 0; i <= 9; i++)
    {
        GPIO_toggleOutputOnPin(GPIO_PORT_P4, GPIO_PIN7);

        __delay_cycles(100000);
    }

    toggle = 0;
}

LPM3;

When the button is pressed, external interrupt kicks in, LPM3 is exited, interrupt flag is cleared and variable toggle is set. Since there is one interrupt vector for the entire P1 port pins, it is needed to be sure which pin caused the interrupt. This is why the state of P1.1 needs to be checked right after interrupt. 

#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR(void)
{
    LPM3_EXIT;

    if(GPIO_getInterruptStatus(GPIO_PORT_P1, GPIO_PIN1) != 0)
    {
        GPIO_clearInterrupt(GPIO_PORT_P1, GPIO_PIN1);

        toggle = 1;
        _nop();
    }
}

Since now the toggle variable is set, P1.0 LED flashes and then P4.7 LED flashes, indicating that an external interrupt has been processed.  

Demo

Pages: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37

Related Posts

14 comments

Leave a Reply

Your email address will not be published. Required fields are marked *