Tool/software: TI C/C++ Compiler
I am working on a device using the MSP430FR5869 which has several active-low buttons, and have been unable to get GPIO interrupts to work correctly. I've used a logic analyzer to confirm that the pin of interest is being pulled up correctly, goes low when I press the button, and returns high when the button is released. However, using the following code, the interrupt service routine fires constantly, even if I never press the button at all. It does this no matter which pin I use. Using Code Composer Studio to view the Port 3 registers, I see that the interrupt flag is always set, and appears to never clear. I've tried clearing the interrupt flag manually, but that doesn't help (and the user manual says that shouldn't be necessary anyway).
Does anyone see something I'm doing wrong?
Thank you,
Adam J.
/******************************************************************************
* This example sets up a pin for an active-low GPIO interrupt. An interrupt
* service routine fires when a pin goes low and decodes which pin it is.
*****************************************************************************/
#include <msp430.h>
#include "driverlib.h" // TI's driver library for MSP430FR5xx_6xx
int main(void)
{
// Stop watchdog timer.
WDTCTL = WDTPW | WDTHOLD;
// Initializes system clocks to 16MHz with 1 wait-state.
FRCTL0 = FRCTLPW | NWAITS_1;
CS_setDCOFreq(CS_DCORSEL_1, CS_DCOFSEL_4);
// Configure MCLK, SMCLK to be sourced by DCOCLK.
CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_4);
CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1);
// Configure as input pins.
GPIO_setAsInputPin(GPIO_PORT_P3, GPIO_PIN7);
// Enable the pull-up resistor.
GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P3, GPIO_PIN7);
// Disable the interrupt.
GPIO_disableInterrupt(GPIO_PORT_P3, GPIO_PIN7);
// Clear any pending interrupts.
GPIO_clearInterrupt(GPIO_PORT_P3, GPIO_PIN7);
// Set interrupt to trigger on a falling edge.
GPIO_selectInterruptEdge(GPIO_PORT_P3, GPIO_PIN7, GPIO_HIGH_TO_LOW_TRANSITION);
// Enable the interrupt.
GPIO_enableInterrupt(GPIO_PORT_P3, GPIO_PIN7);
// Enable global interrupts.
__enable_interrupt();
// Wait here forever.
while (true);
}
/* Port 3 Interrupt Vector for ionKEY_R, ionKEY_U, ionKEY_L, ionKEY_D*/
#pragma vector=PORT3_VECTOR;
__interrupt void port3(void)
{
// This bit will tell us what pin caused the interrupt to fire.
// It's volatile so the compiler won't optimize it away.
volatile uint8_t pin;
// Figure out which pin in the port caused the interrupt.
// You might think that we'd check the interrupt flag register, but no!
// The user manual's example has us check the interrupt vector register.
// Also, clearing the interrupt flag is not necessary, because according to
// the user manual "any access (read or write) of the lower byte of the
// PxIV register (either word or byte access) automatically resets the
// highest pending interrupt flag."
switch (__even_in_range(P3IV, 16))
{
case 0: // Vector 0 - no interrupt
break;
case 2: // Vector 2 - pin 0
pin = 0;
break;
case 4: // Vector 4 - pin 1
pin = 1;
break;
case 6: // Vector 6 - pin 2
pin = 2;
break;
case 8: // Vector 8 - pin 3
pin = 3;
break;
case 10: // Vector 10 - pin 4
pin = 4;
break;
case 12: // Vector 12 - pin 5
pin = 5;
break;
case 14: // Vector 14 - pin 6
pin = 6;
break;
case 16: // Vector 16 - pin 7
pin = 7;// <-- This line will constantly be hit! WHY???
break;
default:
break;
}
}