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.

Difficulty with creating two Interrupt Service Routines at Port 1 and Port2

Other Parts Discussed in Thread: MSP430F5529

Hi everyone,

Using MSP430F5529 Launchpad, I am trying to use 2 push buttons at P1.1 and P2.1 as inputs to produce PWM outputs with varying Duty Cycles. The Duty Cycle (TA0CCR2) is set globally to 100 and the Period (TA0CCR0) to 1000-1 at the beginning of the program. By pressing P1.1 I want the Duty Cycle (DC) to increment by 10% of the period until it reaches to the value of the Period. Similarly by pressing P2.1 I want the DC to decrement by 10% until it reaches to 0.

When I run the code, I only get the initial PWM with DC=100 and it seems the interrupts do not work.

Please review my code and let me know where my problem is.

Thanks very much,

#include <msp430.h>
#include <stdio.h>
#include <math.h>
int Period = 1000-1;
//#pragma LOCATION(DC, 0x2400);
int DC = 100;
int main(void)
{
  WDTCTL = WDTPW + WDTHOLD;         // Stop WDT
for(;;)
{
//push-buttons update
  P1REN |= BIT1; //Enable resistor on P1.1
  P1OUT = BIT1;   //set p1.1 resistor to pull-up
  P2REN |= BIT1; //Enable resistor on P2.1
  P2OUT = BIT1; //set p2.1 resistor to pull-up
   if (((P1IN & 0x02) != 0x02) && (DC <Period)) //if Push-Button1 is pressed and DC<Period
     {
  P1IE |= 0x02;     //enable P1.1 interrupt
  P1IES |= 0x02; //select high to low edge
  P1IFG &= ~0x02; //clear P1.1 flag
  __bis_SR_register(LPM0_bits + GIE);
  __no_operation();
     }
  if(((P2IN & 0x02) != 0x02) && (DC>0)) //if Push-button2 is pressed and DC<0
     {
     P2IE |= 0x02; //Enable P2.1 interrupt
     P2IES |= 0x02; //select hight to low sensitivity
     P2IFG &= ~0x02; //clear P2.1 flag
   __bis_SR_register(LPM0_bits + GIE);
   __no_operation();
     }
  //pwm update
     P1DIR |= BIT3;
     P1SEL |= BIT3;
     TA0CCR0 = Period;
     TA0CCTL2 = OUTMOD_7;
     TA0CCR2 = DC;
     TA0CTL = TASSEL_2 + MC_1; //SMCLK, up mode
     __bis_SR_register(LPM0_bits);
     __no_operation();
}       //for loop end
}       //main end
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
DC = DC + round(0.1*Period); //DC is increased by 10% of the Period
  P1IFG &= ~0x02;
  P1IES ^= 0x02;
}
#pragma vector=PORT2_VECTOR
__interrupt void Port_2(void)
{
DC = DC - round(0.1*Period); //DC is decreased by 10% of the Period
  P2IFG &= ~0x02;
  P2IES ^= 0x02;
}
  • Niloofar, next time when inserting code, please use the syntax highlighter in rich formatting so it is easier to read - it then looks like this:

    #include <msp430.h>
    #include <stdio.h>
    #include <math.h>
    
    int Period = 1000-1;
    
    //#pragma LOCATION( DC, 0x2400 );
    
    int DC = 100;
    
    int main( void )
    {
      WDTCTL = WDTPW + WDTHOLD; // Stop WDT
    
      for(;;)
      {
        //push-buttons update
        P1REN |= BIT1; // Enable resistor on P1.1
        P1OUT  = BIT1; // set p1.1 resistor to pull-up
        P2REN |= BIT1; // Enable resistor on P2.1
        P2OUT  = BIT1; // set p2.1 resistor to pull-up
       
        if( ((P1IN & 0x02) != 0x02) && (DC < Period) ) // if Push-Button1 is pressed and DC<Period
        {
          P1IE  |=  0x02; // enable P1.1 interrupt
          P1IES |=  0x02; // select high to low edge
          P1IFG &= ~0x02; // clear P1.1 flag
      
          __bis_SR_register( LPM0_bits + GIE );
          __no_operation();
        }
      
        if( ((P2IN & 0x02) != 0x02) && (DC > 0) ) // if Push-button2 is pressed and DC<0
        {
          P2IE  |=  0x02; // enable P2.1 interrupt
          P2IES |=  0x02; // select hight to low sensitivity
          P2IFG &= ~0x02; // clear P2.1 flag
          
          __bis_SR_register( LPM0_bits + GIE );
          __no_operation();
        }
    
        //pwm update
        P1DIR   |= BIT3;
        P1SEL   |= BIT3;
    
        TA0CCR0  = Period;
        TA0CCTL2 = OUTMOD_7;
        TA0CCR2  = DC;
        TA0CTL   = TASSEL_2 + MC_1; // SMCLK, up mode
        
        __bis_SR_register( LPM0_bits );
        __no_operation();
      } //for loop end
    } //main end
    
    #pragma vector = PORT1_VECTOR
    __interrupt void Port_1( void )
    {
      DC = DC + round( 0.1 * Period ); // DC is increased by 10% of the Period
      P1IFG &= ~0x02;
      P1IES ^= 0x02;
    }
    
    #pragma vector = PORT2_VECTOR
    __interrupt void Port_2( void )
    {
      DC = DC - round( 0.1 * Period ); // DC is decreased by 10% of the Period
      P2IFG &= ~0x02;
      P2IES ^= 0x02;
    }

    So let's see what is wrong with your code...

  • just a vie thoughts on first sight:

    Dennis Eichmann said:
    P2IES ^= 0x02;

    why do you toggle the edges? doesnt make sense to me,

    Dennis Eichmann said:
    round( 0.1 * Period );

    in a real program never use dificult math in an IRQ, it costs too much time and resources, always do this in your normal code not in th eIRQ, although for testing it is ok, it wont hurt you.

    you sure you need pull ups not pull downs?

    next step I would debug , do you enter the IRQs at all?

    your code seems pretty simple with a simple debug in code composer you should be able to find where it is not doing the things you want it to do.

    Good luck.

  • When you configure the pins or the timer you do not need to do it over and over again in your for(;;)-loop, so you can put all the configuration before the loop:

    int Period = (1000 - 1);
    int DC     = 100;
    
    void main( void )
    {
      WDTCTL = WDTPW | WDTHOLD; // Stop WDT
    
      P1SEL |=  BIT3;
      P1DIR |=  BIT3;
    
      P1REN |=  BIT1; // enable resistor on P1.1
      P1OUT  =  BIT1; // set p1.1 resistor to pull-up
      P1IES |=  BIT1; // select high to low edge
      P1IFG &= ~BIT1; // clear P1.1 flag
      P1IE  |=  BIT1; // enable P1.1 interrupt
      
      P2REN |=  BIT1; // enable resistor on P2.1
      P2OUT  =  BIT1; // set p2.1 resistor to pull-up
      P2IES |=  BIT1; // select hight to low sensitivity
      P2IFG &= ~BIT1; // clear P2.1 flag
      P2IE  |=  BIT1; // enable P2.1 interrupt
    
      TA0CCR0  = Period;
      TA0CCR2  = DC;
      TA0CCTL2 = OUTMOD_7;
      TA0CTL   = TASSEL_2 | MC_1; // SMCLK, up mode
    
      __bis_SR_register( GIE );
    
      for(;;)
      {
        ...
      }
    }
  • seb is right with his comment - using a floating point operation on this processor inside an ISR isn't the best idea in general. If your program will not do anything else, then this might be OK. But I think a floating point operation isn't necessary here. You have a fixed period of 1000, so in-/decrementing 100 does the same. If it will change later to a variable period, then better go for (period / 10), which is still an integer. Or you could also set a new period in your main in combination with another variable that holds the new in-/decrement value which will be calculated at the same time the new period is set.

    Then you will run into the typical button problem: bouncing

    You always have to debounce buttons with a delay (bad way) or a timer. The timer method is more complex, of course. If you want to use interrupts for the input buttons, you could start a timer inside the button-ISR and check the button's state in the timer interrupt again. If it is still pressed, do the desired action.

    But you could also read your buttons in periodic intervals controlled by a timer.

    And to seb's other statement: Why do you change the PxIES? I also don't get why you handle the buttons inside the main and inside the ISR. Maybe you describe what you originally had planned.

  • Hi Dennis, thank you so much for reviewing the code. I make sure to use the syntax highlighter in rich formatting in future.
  • Thank you very much for your valuable comments.
    Regarding the duty cycle, is there anyway that I can store this value in RAM and update it as it changes? From the datasheet I see the address of 4 sectors of RAM, but I am not sure which one I can use.

    Sorry that my posted program does not make good sense, but following your comments I am updating it. I'll post the new program in a few days and would greatly appreciate if you review it.
  • What exactly are you talking about witht he 4 secot of RAM?

    MSP430F only has flash and RAM, maybe you should be aware of how your program code works first?!

    Almost everything you write in code in C-language will be stored in RAM during runtime, only const will be stored in Flash. And flash is not easily changed during runtime, since it is not easily eraseable.

    So your Duty cycles will be in RAM. But i am not sure yet how that would make your whole Code work or not work.

**Attention** This is a public forum