Based on Dr Marty’s work, which was declared by himself to be the best switch debounce routine ever, I developed one for my project, for which a push button is used to control program flow. In order to make the control fine a push of the button is distinguished as long or short depending on the length of the push.
1. Create two uint32_t variables: buttonPressed and buttonReleased, set their initial values to zero.
2. configure the watchdog timer as interval timer that is enabled to generate continuous overflow interrupts and do time counting.
3. initialize the pin P3.1 as input, connect a push button to it, enable interrupts for the pin, and set its interrupt on lowto-high transition.
4. implement the interval timer ISR by one command: timeCounting ++, one does not need to clear interupt flag as documents say that it will be cleared automatically once the ISR is executed.
5. implement the P3 ISR:
- clear interrupt flag.
- if a low-to-high interrupt was first detected (buttonPressed = 0), XOR P3 interupt edge, and set buttonPressed = timeCounting
- else a high-to-low interrupt was detected (buttonPressed >0), just set buttonReleased = timeCounting.
6. get time of button pressing plus bouncing = buttonReleased – buttonPressed, then a long or short button press can be determined.
It sounds good, right!
But I do not know if it will really works or not. Below is the code, please take a look and give it a evaluation.
uint32_t buttonPressed=0,buttonReleased=0; bool longButton; int main(void) { //set interval timer WDTCTL = WDTPW | WDTHOLD; WDTCTL = WDTPW | WDTSSEL__ACLK | WDTTMSEL | WDTCNTCL | WDTIS_5; //250 ms a count __enable_interrupt(); NVIC_ISER0 = 1 << ((INT_WDT_A - 16) & 31); //set P3.1 P3DIR &= ~(uint8_t) BIT1; P3REN |= BIT1; // Enable pull-up resistor (P3.1 output high) P3SEL0 = 0; P3SEL1 = 0; P3IFG &= ~BIT1; // Clear all P3 interrupt flags P3IE = BIT1; // Enable interrupt for P3.1 P3IES &= ~BIT1; // Interrupt on low-to-high transition NVIC_ISER1 = 1 << ((INT_PORT3 - 16) & 31); for(;;) { MAP_PCM_gotoLPM3(); //go into LPM3, wake up when button pressed while ((P3IN & BTN1) == ~BTN1); // wait for button bouncing stable buttonReleased -= buttonPressed; //How long it takes from the first low-to-high transition to the last high-to-low. if (buttonReleased>15) continue; //too long should be excluded as probably the first low-to-high is a noice if (buttonReleased<1) continue; //too short should be excluded too. longButton=buttonReleased>5; //>5, at least 6 time counts, 6*0.25 s = 1.5 s, < 15*0.25 = 3.75 s P3IES &= ~BIT1; //low-to-high transition for next button press ... ... //do some things here for long or short press buttonPressed = 0; //reset it to zero for next one } } void WdtIsrHandler(void) { timeCounting ++; //do not need cleaning interrupt flag, see comments above } void Port3Handler(void) { P3IFG &= ~BIT1; //clear port3 interrupt if (buttonPressed==0) { P3IES ^= BIT1; //change interrupt edge buttonPressed = timeCounting;} else buttonReleased = timeCounting; }