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.

MSP432 button interrupt problem

Hy guys,

i' m working with the method of using interrupts instead of the standard polling method.

I used the code below, but the compiler says " The symbol used in #pragma vector= requires a declaration".

Do you know what that mean?


Chris


#include "msp.h"

#define LED0 BIT0
#define BUTTON BIT3



int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer
P1DIR |= LED0; // Set P1.0 to output direction
// P1.3 must stay at input
P1OUT &= ~LED0; // set P1.0 to 0 (LED OFF)
P1IE |= BUTTON; // P1.3 interrupt enabled

P1IFG &= ~BUTTON; // P1.3 IFG cleared

__enable_interrupt(); // enable all interrupts
for(;;)
{}
}


// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
P1OUT ^= LED0; // P1.0 = toggle
P1IFG &= ~BUTTON; // P1.3 IFG cleared
P1IES ^= BUTTON; // toggle the interrupt edge,
// the interrupt vector will be called
// when P1.3 goes from HitoLow as well as
// LowtoHigh
}

  • I found some explaination in an other blog. They say that the code mentioned above is only running, with no modification, on the MSP430. When you use the MSP432 you have to do the configuration for the NVIC.
    In the first step I have to set the Port 1 Interrupt Vector Register (PxIV) and than enable the module interrupt in NVIC. At the end I have to enable the NVIC Master Interrupt.

    1. step --> P1IV|=04;
    2. step --> ???
    3.step --> __enable_interrupt();

    Does anybody know how to realize the 1st and the 2nd step?

    Chris
  • Hi Christoph!

    For the MSP432 you should configure the interrupt vector table. Look at the MSP432 platform porting guide that can be downloaded here.

    Dennis

  • Thank you Dennis i configured the interrupt table like this:

    msp432_startup_ccs.c:

    ...
    /*External declarations for the interrupt handlers used by the application*/
    extern void Port1IsrHandler(void)
    ...

    Port1IsrHandler, /*PORT1 ISR*/


    In the main.c I realized it like this:

    void main(void)
    {
    WDTCTL=WDTPW | WDTHOLD;
    P1DIR|=BIT0; //set the output and input
    P1OUT&=~BIT0; //red LED off

    P1IE|=BIT1; //Button interrupt enable
    P1REN|=BIT1; //enable pull-up
    P1IFG&=~BIT1; //clear interrupt flag

    __enable_interrupt();
    NVIC_ISER0 = 1 << ((INT_PORT1 - 16) &31);

    while(1)
    {
    }

    }

    void Port1IsrHandler(void)
    {
    P1OUT^=BIT0;
    P1IFG&=~BIT1;
    P1IES^=BIT1;
    }

    But it does't work.
    Do you know why?

    Chris,
  • Christoph Marko said:
    But it does't work.
    Do you know why?

    That sounds good :) I guess you mean it does not work?

    Isn't the ISR accessed? Did you set a breakpoint inside the ISR? Interrupts for buttons are somhow critical because the contact bouncing will act as multiple presses. If you do not care for this, the code behaves different from what expected. And always change the PIES before clearing the IFG because changes can set the IFG.

    Dennis

  • And PORT1 has the interrupt number 51. If you subtract 16 from it, you will have 35. This is beyond the NVIC_ISER0 range of 31 maximum. So this interrupt has to be enabled in NVIC_ISER1.

    Dennis
  • Yeah I meant it doesn't work so the LED doesn't turn on and off.
    Could you realize it without debouncing?
  • Did you change the NVIC setting? For debouncing buttons you could use a timer that reads the keys every 10ms, for example. Read the button, save it's state and in the next timer cycle look if the new state is different to the previous one - if so, save that. If this changed state is still present in the next cycle, report the button press to the application. Even the worst button will normally not bounce longer than 10ms.

    The poor man's method is to add a delay after the detected button press to wait for finishing the bouncing, but that also affects your program flow. Or you can use a port interrupt and start a timer in the port ISR while simultaneously disable further interrupts for the button. Set the timer to invoke an ISR after 10ms. Inside the ISR, check if the button is still pressed and report it to the application. Change everything to the other edge to detect the release. If not, reset everything because the button was released too early.

    There are a few ways, but the timer method without interrupts is the one I prefer.

  • Ok i changed the settings, but didn't use the timer interrupt, but I will do this later.
    I have a further question is it possible to use a software delay instead of the timer interrupt?
  • Yes, sure, but as I said, this delay will also delay the rest of your program. This would be a poor method:

    void main( void )
    {
      ...
    
      while( 1 )
      {
        ...
    
        if( BUTTON_IS_PRESSED )       // If button is currently pressed
        {
          delay();                    // Delay for debouncing
    
          while( BUTTON_IS_PRESSED ); // Wait for release again
    
          // Do something
        }
      }
    }

  • So am I right that i only need a Timer interrupt or do I need a timer and a button interrupt?
  • I changed the P1IES command with the P1IFG command --> now it works, but when I release the button the LED turn off, a few seconds later.

**Attention** This is a public forum