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.

CCS/MSP430G2553: Code for ISR pushbutton doesn't pause variation of the PWM duty cycle

Part Number: MSP430G2553

Tool/software: Code Composer Studio

I'm trying to incorporate an Interrupt Service Routine (ISR) for the pushbutton in the msp430 launchpad, so that pushing the button pauses the variation of the PWM duty cycle (and thus the red LED brightness remains constant). When the button is pushed again, the PWM variation resumes (at the same duty cycle value and “direction”, prior to the first button push). However, when I push the button nothing happens; the red LED continues changing intensity. Can anyone help me and see why the button is not functioning?

I did my implementation for PWM in timerA.c

#include "LED.h"
#include "timerA.h"

void ConfigureTimerA(void)
{
   TA0CTL  =   (MC0   |   TACLR);
   TA0CTL  |=  (TASSEL_2 |ID_2  |   MC_1);
   //assign value to Time A0; capture/compare register0
   TA0CCR0 =   499;
   TA0CCR1 = 0;
  //enable capture
   TA0CCTL0    |=  CCIE;
   TA0CCTL1    |=  CCIE;
   TA0CTL      |=  TAIE;
}
unsigned int direction = 0;
#pragma vector = TIMER0_A0_VECTOR
// Interrupt service routine for CCIFG0
	__interrupt void Timer0_A0_routine(void)
{
    //light at min intensity
   if(TACCR1 == 0)
      direction = 1;
   //light at max intensity
   else if (TACCR0 == TACCR1)
       direction = 0;

}

#pragma vector = TIMER0_A1_VECTOR
// Interrupt service routine for CCIFG1 and TAIFG
	__interrupt void Timer0_A1_routine(void)
{
	    //if both TAIFG (on) and CCR1 (off) interrupts are indicated, the net effect on the LED
	    //is null.
	    unsigned on, off;            // (16-bit)
	         off = TA0CTL & TAIFG;
	         on = TA0CCTL1 & CCIFG;
	         if (on && off){
	             // do nothing
	             TA0CTL &= ~TAIFG;
	             TA0CCTL1 &= ~CCIFG;
	         }
	         else if (off){
	             TURN_OFF_LED1;
	             TA0CTL &= ~TAIFG;
	         }
	         else if (on){
	             TURN_ON_LED1;
	             TA0CCTL1 &= ~CCIFG;
	         }
	         else{
	             for (;;);   // Should not be possible
	         }
	         if (on){  // CCR1
	            //light at min increase duty cycle
	            if(direction == 0)
	                TACCR1 --;
	            //light at max decrease duty cycle
	            else if(direction == 1)
	                TACCR1++;
	         }

}

This is where I'm implementing the button

#include "pushbutton.h"
#include "LED.h"

void InitializePushButtonPortPin (void)
{

    P1DIR  &=~BIT3;
    P1REN |= BIT3;
    P1OUT |= BIT3;
    P1IE |= BIT3;
    P1DIR &= ~BIT6;
}

#pragma vector = PORT1_VECTOR
// Button interrupt service routine
__interrupt void Button_routine(void)
{
    TA0CCTL0 ^= CCIE;
    P1IFG &= ~BIT3;
}

 This is my main method

#include <msp430.h>
#include "LED.h"
#include "pushbutton.h"
#include "timerA.h"

// Global variable
char LEDBit = LED1;

// Function prototypes
void ConfigureClockModule(void);

void main(void)
{
    // Stop the watchdog timer, and configure the clock module.
    WDTCTL = WDTPW + WDTHOLD;
    ConfigureClockModule();

    // Initialize port pins associated with the LEDs, and then turn off LEDs.
    InitializeLEDPortPins();


    // Configure timer A to generate the required interrupt.
    ConfigureTimerA();

    _enable_interrupts();

    // Infinite loop
    while (1) {

    }
}
void TimeDelay(unsigned int delay, unsigned int resolution){
    unsigned i;
    TA0CTL = (MC_0 |TACLR);
    TA0CCR0 = resolution;
    TA0CTL = (TASSEL_2|ID_2|MC_1);

    for(i=0; i<delay; i++){
        while(!(TA0CTL & TAIFG));
        TA0CTL &= !TAIFG;

        TA0CTL =(MC_0 |TACLR);
    }
}

void ConfigureClockModule(void)
{
    // Configure Digitally Controlled Oscillator (DCO) using factory calibrations.
    DCOCTL  = CALDCO_1MHZ;
    BCSCTL1 = CALBC1_1MHZ;
}

  • Hi Maria,

    I couldn't find the place in your code where you call InitializePushButtonPortPin(). So it looks like you're never initializing your push button pin. Additionally, I would recommend adding a debounce routine so that the the ISR isn't triggered multiple times from one button push.

    Finally, in your button push ISR I recommend clearing the CCIE with TA0CCTL0 &= ~CCIE; instead of XORing the register.

    Best regards,
    Caleb Overbay
  • I initialized the button on the pushbutton.h file
    #ifndef PUSHBUTTON_H
    #define PUSHBUTTON_H
    #define BUTTON BIT3


    #include <msp430.h>

    // Prototypes
    void InitializePushButtonPortPin(void);

    #endif
  • Hi Maria,

    That's still not a call to the InitializePushButtonPortPin routine. It's simply a function prototype. That means the initialization code is never getting executed.

    When you place a breakpoint inside the pushbutton ISR and push the button, does the code enter the ISR? If not this means the button is not being initialized. You should add a call to the InitializePushButtonPortPin routine in your main().

    Best regards,
    Caleb Overbay
  • Right next to InitializeLEDPortPins() would be a good place. 8^)
  • So I did on the main, but now the pushbutton is turning the LED off not holding the intensity of the LED
    void main(void)
    {
    // Stop the watchdog timer, and configure the clock module.
    WDTCTL = WDTPW + WDTHOLD;
    ConfigureClockModule();

    // Initialize port pins associated with the LEDs, and then turn off LEDs.
    InitializeLEDPortPins();

    // Initialize the port pin associated with the pushbutton
    InitializePushButtonPortPin();

    // Configure timer A to generate the required interrupt.
    ConfigureTimerA();

    _enable_interrupts();

    // Infinite loop
    while (1) {

    }
    }
  • As I understand it, you want the blinking to continue, but (a) button press N stops incrementing/decrementing CCR1, then (b) press (N+1) re-starts it? So you want to keep the state machine running (blinking), just not alter CCR1.

    I propose a state variable:
    volatile uint8_t stalled; // initially not stalled

    then when you're about to change CCR1, add a condition that the sweep not be "stalled":
    if (on && (!stalled)){ // CCR1

    Then in the port interrupt flip the variable (rather than the CCIE) between 0 and 1:
    stalled ^= 1; // stall if running, run if stalled

    Caleb mentioned debouncing, and he's correct. My observation is that the G2 Launchpad buttons don't bounce much, so maybe you can get away with ignoring it for the moment to get this other thing going. You won't be able to ignore it for long though; when you start seeing apparent multiple button pushes, google "ganssle debounce". I consider his article a Standard Text -- both interesting and useful.

  • I did what you said, but the LED is turning off when I press the button. It's suppose to hold the intensity
  • My guess is that you didn't remove the line
    > TA0CCTL0 ^= CCIE;
    from Button_routine.

**Attention** This is a public forum