TI-RTOS - HWI Button Presses w/Debounce
In my last blog post, I covered how to add Hardware Interrupts to handle the Button presses on the MSP432. But, as Jan Cumps pointed out, to get reliable button presses, Debounce handlers should be added.
See previous post:
Safe and Sound Wearables- Hearing Guard System #8: TI-RTOS Enable Button HWI
In this post, I'll show a simple way to add a mechanism to reduce the debounce occurrences when a Button is pressed on the MSP432.
So, what is Switch or Button debounce you might ask? The Buttons on the MSP432 at SW1 and SW2 are mechanical devices that engage when a user presses the Button on the switch causing a metal contact from the Button to make contact with a metal contact on the main body of the switch. Instead of the two contacts making a clean connection, they actually bounce a bit causing what is known as Switch Bounce. These micro bounces typically have a duration between 10us and 300us. As the duration gets longer, strange behavior can occur where it can appear that multiple button presses were performed when only 1 occurred. This can be an issue causing a program to either record false button presses or miss a button press depending on how the application is coded.
To reduce the bounce in the circuit, it is not practical to change the behavior of the metal contacts, so the next best option is to code around this behavior. There are various options ranging from rechecking the button press if an event is seen, or adding some sort of loop to wait for the switch press to settle a bit before checking the state of the button press. In this example, the later will be implemented.
Using the same gpiointerrupt_MSP_EXP432P401R_TI example from the previous post, the debug code can be easily added using the TI_RTOS Clock API.
First, added the TI_RTOS Clock.h head to the top of the file where the main function resides.
#include <ti/sysbios/knl/Clock.h>
Next, create Clock Handle for both Button0 and Button1 (SW1 and SW2)
/* Clock handles for Button0 and Button1 (SW1 and SW2) */ Clock_Handle clockHandle0, clockHandle1;
Then, either at the top of the main function, or in a initialization function, at the following code to initialize the Clock to handle the Button press events.
/* initialize the Clock parameters */ Clock_Params_init(&clockParams); clockParams.period = 0; /* set the start Flag to F */ clockParams.startFlag = FALSE; /* Define a clock Handle for button */ clockHandle0 = Clock_create(debounceFxn0, 10, &clockParams, NULL); clockHandle1 = Clock_create(debounceFxn1, 10, &clockParams, NULL);
Then add the Function Handler definitions for the Clock events
/* Clock handlers for Button0 and Button1 (SW1 and SW2) */
Clock_Handle clockHandle0, clockHandle1;
Void debounceFxn0(UArg arg)
{
GPIO_toggle(Board_LED0);
if (count++ == 100) {
count = 0;
}
}
Void debounceFxn1(UArg arg)
{
GPIO_toggle(Board_LED1);
if (count++ == 100) {
count = 0;
}
}
To, add the Debounce methods to the Button presses, the Interrupt methods for the Buttons require, modification. The GPIO_Toggle methods have been moved to the Clock handlers and a Clock_start method has been added to each Button HWI Handler to start the debounce timer. This should prevent from the code registering multiple button presses on a single press.
/*
* ======== gpioButtonFxn0 ========
* Callback function for the GPIO interrupt on Board_BUTTON0.
*/
void gpioButtonFxn0(unsigned int index)
{
/* Clear the GPIO interrupt and toggle an LED */
/*
GPIO_toggle(Board_LED0);
if (count++ == 100) {
count = 0;
}
*/
Clock_start(clockHandle0);
/* Clear the GPIO interrput */
GPIO_clearInt(Board_BUTTON0);
}
/*
* ======== gpioButtonFxn1 ========
* Callback function for the GPIO interrupt on Board_BUTTON1.
* This may not be used for all boards.
*/
void gpioButtonFxn1(unsigned int index)
{
/* Clear the GPIO interrupt and toggle an LED */
/*
GPIO_toggle(Board_LED1);
if (count++ == 100) {
count = 0;
}
*/
Clock_start(clockHandle1);
/* Clear the GPIO interrput */
GPIO_clearInt(Board_BUTTON1);
}
That is about it for the Debounce Functions.
As a bonus, if you are like me and would like to have access to the RGB LEDs on the MSP432 Launchpad, a few changes are needed to enable these in TI-RTOS.
NOTE: The same GPIO pins for the RGB LEDs are tied to the PWM capability on the board, so if you need the PWM implementation, then skip this.
In the Board.h header file, the two lines that define Board_LED2(MSP_EXP432P401R_LED_GREEN) and Board_LED3 (MSP_EXP432P401R_LED_GREEN) need to be uncommented, Also, the define for Board_LED2 that defines it for the Red LED should be commented out.
#define Board_LED1 MSP_EXP432P401R_LED_RED //#define Board_LED2 MSP_EXP432P401R_LED_RED /* * MSP_EXP432P401R_LED_GREEN & MSP_EXP432P401R_LED_BLUE are used for * PWM examples. Uncomment the following lines if you would like to control * the LEDs with the GPIO driver. */ #define Board_LED2 MSP_EXP432P401R_LED_GREEN #define Board_LED3 MSP_EXP432P401R_LED_BLUE
Then, in MSP_EXP432P401R.h, at about line 70, uncomment out the entries for LED_GREEN and LED_BLUE .
typedef enum MSP_EXP432P401R_GPIOName {
MSP_EXP432P401R_S1 = 0,
MSP_EXP432P401R_S2,
MSP_EXP432P401R_LED1,
MSP_EXP432P401R_LED_RED,
/*
* MSP_EXP432P401R_LED_GREEN & MSP_EXP432P401R_LED_BLUE are used for
* PWM examples. Uncomment the following lines if you would like to control
* the LEDs with the GPIO driver.
*/
MSP_EXP432P401R_LED_GREEN,
MSP_EXP432P401R_LED_BLUE,
MSP_EXP432P401R_GPIOCOUNT
} MSP_EXP432P401R_GPIOName;
In MSP_EXP432P401R.h, uncomment the entries in the gpioPinConfigs array for LED_GREEN and LED_BLUE
GPIO_PinConfig gpioPinConfigs[] = {
/* Input pins */
/* MSP_EXP432P401R_S1 */
GPIOMSP432_P1_1 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
/* MSP_EXP432P401R_S2 */
GPIOMSP432_P1_4 | GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_RISING,
/* Output pins */
/* MSP_EXP432P401R_LED1 */
GPIOMSP432_P1_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
/* MSP_EXP432P401R_LED_RED */
GPIOMSP432_P2_0 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
/*
* MSP_EXP432P401R_LED_GREEN & MSP_EXP432P401R_LED_BLUE are used for
* PWM examples. Uncomment the following lines if you would like to control
* the LEDs with the GPIO driver.
*/
/* MSP_EXP432P401R_LED_GREEN */
GPIOMSP432_P2_1 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW,
/* MSP_EXP432P401R_LED_BLUE */
GPIOMSP432_P2_2 | GPIO_CFG_OUT_STD | GPIO_CFG_OUT_STR_HIGH | GPIO_CFG_OUT_LOW
};
In the main function, added the entries for the Green and Blue LEDs for Board_LED2 and Board_LED3.
/* Turn on user LED */
GPIO_write(Board_LED0|Board_LED2|Board_LED3, Board_LED_ON);
Now, in the Debounce methods for the Button handlers, the newly enabled Green And Blue LEDs can be used in place of the Red LED.
Void debounceFxn0(UArg arg)
{
GPIO_toggle(Board_LED2);
if (count++ == 100) {
count = 0;
}
}
Void debounceFxn1(UArg arg)
{
GPIO_toggle(Board_LED3);
if (count++ == 100) {
count = 0;
}
}
This is an example showing the Buttons on the MSP432 being enabled within TI-RTOS but this time with the Debounce code implemented. Also, the GREEN and BLUE LEDs have been enabled to bring color to the button presses. And, piece of the Menu code I have been working on is included to show case stepping through menu options using the button presses in TI-RTOS.
Top Comments