Jump to content
43oh

Recommended Posts

I am trying to write a simple button interrupt debounce routine without much success.  I am seeing unexpected interrupts occurring.  

 

The logic I am using is to disable the button interrupt when first pressed and then re-enabling it when the watch dog timer expires.  I have tried increasing the wdt interval but the momentary switch button is still bouncing and simply fires the button interrupt unexpectedly.

 

I know I can write other debounce routines but I would like to stay out of polling or looping for low power reasons if at all possible.  I am not sure if the issue is something with the wdt so I am also looking at using timerA instead of the wdt.

 

Thanks for any guidance/suggestions.

#include <msp430g2553.h>

#define     BUTTON                BIT3 //0x08

int main(void) {
	WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer

	P1REN |= BUTTON; // enable pull up resistor on P1.3 button
	P1DIR |= 0x01; // Set P1.0 to output direction
	P1IE |= BUTTON; // P1.3 interrupt enabled
	P1IES |= BUTTON; // P1.3 Hi/lo edge
	P1IFG &= ~BUTTON; // P1.3 IFG cleared - set to correct state first time

	__enable_interrupt(); // enable all interrupts

	while(1)
	{
		//check flags set by interrupts here, do something, clear flag
	}

	//return 0;
}

// Port 1 interrupt service routine
#pragma vector=PORT1_VECTOR
__interrupt void Port_1(void)
{
	//__bic_SR_register_on_exit(LPM4_bits); // clear original LPM4 Bit to wake up clocks and cpu
	P1IFG &= ~BUTTON;                 // Clear the interrupt flag for the button
	P1IE &= ~BUTTON;                  // Disable Button interrupt
	//WDTCTL = WDT_MDLY_32;             // Set watchdog timer (WDT) to trigger every 32ms
	WDTCTL = WDT_ADLY_1000;
	IE1 |= WDTIE;                     // enable WDT interrupt

	P1OUT ^= 0x01; // P1.0 = toggle (toggle led)
}

// WDT Interrupt Service Routine used to de-bounce button press
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
    IE1 &= ~WDTIE;                   // disable Watchdog timer (WDT) interrupt
    IFG1 &= ~WDTIFG;                 // clear WDT interrupt flag
    WDTCTL = WDTPW + WDTHOLD;        // put WDT back in hold state
    P1IE |= BUTTON;                  // Reenable interrupts for the button
}
Link to post
Share on other sites

There was an excellent article series on HackADay a few weeks back that poured cold water on the R/C Filter Debounce solution, and offered several software solutions instead. I've always tried to avoid R/C solutions myself because of the added parts count, but it was nice to read about with other people were doing to solve this issue.

 

http://hackaday.com/2015/12/09/embed-with-elliot-debounce-your-noisy-buttons-part-i/

 

http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/

Link to post
Share on other sites

There was an excellent article series on HackADay a few weeks back that poured cold water on the R/C Filter Debounce solution, and offered several software solutions instead. I've always tried to avoid R/C solutions myself because of the added parts count, but it was nice to read about with other people were doing to solve this issue.

 

http://hackaday.com/2015/12/09/embed-with-elliot-debounce-your-noisy-buttons-part-i/

 

http://hackaday.com/2015/12/10/embed-with-elliot-debounce-your-noisy-buttons-part-ii/

Thanks for those links.  That 2nd one is pretty freaking awesome!  Alas if one doesn't want to bother with a periodic timer interrupt to poll the button... the R-C (or R-C+logic chip) option seems easier to me :)

Link to post
Share on other sites

Regardless of the value in the InterruptEnable (PxIE) register the InterruptFlag (PxIFG) register will be set when an edge transition matching the value in InterruptEdgeSelect (PxIES) register.

 

If that bit is set when you re-enable the interrupt wont that trigger another P1 interrupt? To remove this occurrence you just need to re-clear the flag once the WDT timeout has occurred.  That being said, you may still see an interrupt occur on switch release.

// WDT Interrupt Service Routine used to de-bounce button press
#pragma vector=WDT_VECTOR
__interrupt void WDT_ISR(void)
{
    IE1 &= ~WDTIE;                   // disable Watchdog timer (WDT) interrupt
    IFG1 &= ~WDTIFG;                 // clear WDT interrupt flag
    WDTCTL = WDTPW + WDTHOLD;        // put WDT back in hold state
    P1IFG &= ~BUTTON;                // clear pending interupt
    P1IE |= BUTTON;                  // Reenable interrupts for the button
}
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...