Hi. I have a MSP430G2553 that I am using to develop a system to select from one of four options using leds as indicators of which option is currently selectable and a push button to make the selection. The way I have the code configured, it works as expected something close to 80% of the time. My question is can anyone see how I have incorrectly coded this given that the trace on an oscilloscope shows observed button bounce is shorter than software debounce time?
In the code, I use Timer1_A1 in continuous mode to cycle between 4 leds with a delay. I have used a software debounce (from bennthomsen.wordpress.com/engineering-toolbox/ti-msp430-launchpad/using-the-switches/) that uses the watchdog timer set to create a 32ms delay (WDT_MDLY_32) before re enabling the interrupt on the push button pin. The interrupt is set to trigger on a low-to-high transition and the pin is pulled up so that the button triggers the interrupt on release. I have only observed bounce times on the order of < 200 us on this breadboarded circuit so either I didn't set the button up correctly or I have failed to implement the watchdog software delay correctly.
Thanks for any help that you can provide!
Nick
#include <msp430.h>
#define LED1 BIT4
#define LED2 BIT5
#define LED3 BIT0
#define LED4 BIT1
#define PB1 BIT2
volatile int timerOverflow = 0;
volatile int pushButtonPressed = 0;
void turnOffLeds(void);
/*
* main.c
*/
int main(void) {
int selectingLED = 1;
int ledPosit = 0;
int myLeds[4] = {LED1, LED2, LED3, LED4};
WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer
//set ports as i/o
P1SEL = 0;
P1SEL2 = 0;
P1DIR |= (LED1 + LED2);
P1OUT &= ~(LED1 + LED2); //turn these off
P2SEL = 0;
P2SEL2 = 0;
P2DIR |= (LED3 + LED4);
P2OUT &= ~(LED3 + LED4); //turn these off
//start with this LED ON
P1OUT = LED1;
//set up pushbutton
P2DIR &= ~PB1; // set up as input pin
P2REN |= PB1; // enable pull up/down resistor
P2OUT |= PB1; // select pull up
P2IES &= ~PB1; // enable interrupt to trigger on rising edge
P2IFG &= ~PB1; // clear interrupt flag
P2IE |= PB1; // enable interrupts on this pin
/*
* MC_2 continuous up, ID_3 input divide by 8, TASSEL_2 SMCLK, enable interrupt
*/
TA1CTL = MC_2 + TASSEL_2 + ID_3 + TAIE;
__enable_interrupt();
for(;;)
{
int lpbPressed = pushButtonPressed;
if(lpbPressed == 1)
{
if (selectingLED == 1)
{
// disable timer interrupt
TA1CTL &= ~TAIE;
selectingLED = 0;
}else{
//enable timer interrupt and back to displaying LEDs
TA1CTL |= TAIE;
selectingLED = 1;
//turnOffLeds();
}
pushButtonPressed = 0;
//enable push button interrupt
P2IE |= PB1;
}
if(timerOverflow == 1)
{
timerOverflow = 0;
//turn off all leds
turnOffLeds();
if (ledPosit < 2) //check for PORT1
{
P1OUT |= myLeds[ledPosit];
}else{ // must be PORT2
P2OUT |= myLeds[ledPosit];
}
if (ledPosit > 2)
{
ledPosit = 0;
}else{
ledPosit = ledPosit + 1;
}
}
}
return 0;
}
void turnOffLeds(void)
{
P1OUT &= ~(LED1 + LED2);
P2OUT &= ~(LED3 + LED4);
}
#pragma vector = PORT2_VECTOR
__interrupt void PORT2_ISR (void)
{
P2IFG &= ~PB1; // clear flag
P2IE &= ~PB1; // disable interrupt
/*
WDTCTL = WDT_MDLY_32; // start and set WD timer for btn debounce
IFG1 &= ~WDTIFG; // clear flag
IE1 |= WDTIE; // enable WDT interrupt
*/
pushButtonPressed = 1;
}
#pragma vector = WDT_VECTOR
__interrupt void WDT_ISR(void)
{
IE1 &= ~WDTIE; // disable WDT
IFG1 &= ~WDTIFG; // clear flag
WDTCTL = WDTPW | WDTHOLD; // stop WD
//enable push button interrupt
P2IE |= PB1;
}
#pragma vector = TIMER1_A1_VECTOR
__interrupt void Timer1_A1_ISR (void)
{
static int timerCounter = 0;
switch(TA1IV){
case 10://overflow TA1IFG
{
if (timerCounter == 3)
{
timerOverflow = 1;
timerCounter = 0;
}else{
timerCounter = timerCounter + 1;
}
break;
}
default:
//oops
break;
}
}