BSP430  20141115
Board Support Package for MSP430 microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
Bootstrapping a New Platform: Button

This example shows how to use the BSP430 standard button definitions to track button presses and releases.

Note that this application uses a model where interrupts are only enabled when the MCU enters a low-power mode, i.e. inactive, and are disabled when the MCU becomes active again. It is this feature that ensures that interrupts correctly reflect press and release events in the presence of "bounce" in the button. ("Bounce" here means that momentary contact and release causes multiple high/low transitions in the port input signal on a signal press/release event.)

main.c

#include <bsp430/clock.h>
#if ! (BSP430_PLATFORM_BUTTON0 - 0)
#error No button available on this platform
#endif /* BSP430_PLATFORM_BUTTON0 */
typedef struct sButtonState {
sBSP430halISRIndexedChainNode button_cb; /* Callback structure */
const unsigned char bit; /* Bit for button */
volatile unsigned int in_mask; /* Bit set if button is pressed */
volatile unsigned int count; /* Number of interrupts occured */
} sButtonState;
static int
button_isr_ni (const struct sBSP430halISRIndexedChainNode * cb,
void * context,
int idx)
{
sButtonState * sp = (sButtonState *)cb;
++sp->count;
/* Record whether the button is currently pressed based on the edge
* type we captured (1 means transition to 0 = released, 0 means
* transition to 1 = pressed). Configure to detect a state change
* opposite of the one we just captured, regardless of what that
* state might be. This algorithm coupled with interrupts being
* disabled outside of LPM helps ensure we interleave
* pressed/released notifications even in the presence of
* bounces. */
sp->in_mask = (hpl->ies & sp->bit) ^ sp->bit;
hpl->ies ^= sp->bit;
vBSP430ledSet(0, -1);
/* Wakeup. Whether this clears #GIE depends on
* #configBSP430_CORE_LPM_EXIT_CLEAR_GIE */
}
static sButtonState button_state = {
.button_cb = { .callback_ni = button_isr_ni },
};
void main ()
{
volatile sBSP430hplPORTIE * b0hpl;
cprintf("\nbutton " __DATE__ " " __TIME__ "\n");
cprintf("There's supposed to be a button at %s.%u\n",
b0pin);
if (! b0hal) {
cprintf("Whoops, guess it's not really there\n");
return;
}
button_state.button_cb.next_ni = b0hal->pin_cbchain_ni[b0pin];
b0hal->pin_cbchain_ni[b0pin] = &button_state.button_cb;
#if (BSP430_PORT_SUPPORTS_REN - 0)
#endif /* BSP430_PORT_SUPPORTS_REN */
button_state.in_mask = BSP430_PLATFORM_BUTTON0_PORT_BIT;
} else {
button_state.in_mask = 0;
}
cprintf("Button is configured. Try pressing it. No debouncing is done.\n");
#if ! (configBSP430_CORE_LPM_EXIT_CLEAR_GIE - 0)
cprintf("WARNING: Interrupts remain enabled after wakeup\n");
#endif /* configBSP430_CORE_LPM_EXIT_CLEAR_GIE */
while (1) {
static const char * state_str[] = { "released", "pressed" };
cprintf("Count %u, in mask 0x%02x: %s\n", button_state.count, button_state.in_mask, state_str[!button_state.in_mask]);
/* Note that we've never turned interrupts on, but
* BSP430_CORE_LPM_ENTER_NI() does so internally so the ISR can be
* executed. Whether they are cleared before returning to this
* loop depends on #configBSP430_CORE_LPM_EXIT_CLEAR_GIE. */
#if ! (configBSP430_CORE_LPM_EXIT_CLEAR_GIE - 0)
/* Infrastructure didn't clear this, so we should */
#endif /* configBSP430_CORE_LPM_EXIT_CLEAR_GIE */
}
}

bsp430_config.h

/* Use a crystal if one is installed. Much more accurate timing
* results. */
#define BSP430_PLATFORM_BOOT_CONFIGURE_LFXT1 1
/* Application does output: support spin-for-jumper */
#define configBSP430_PLATFORM_SPIN_FOR_JUMPER 1
/* Support console output */
#define configBSP430_CONSOLE 1
/* By default run with interrupts disabled whenever CPU is in active mode */
#ifndef configBSP430_CORE_LPM_EXIT_CLEAR_GIE
#define configBSP430_CORE_LPM_EXIT_CLEAR_GIE 1
#endif /* configBSP430_CORE_LPM_EXIT_CLEAR_GIE */
/* Monitor uptime and provide generic ACLK-driven timer */
#define configBSP430_UPTIME 1
/* Request a button */
#define configBSP430_PLATFORM_BUTTON0 1
/* Get platform defaults */

Makefile

PLATFORM ?= exp430fr5739
MODULES=$(MODULES_PLATFORM)
MODULES += $(MODULES_UPTIME)
MODULES += $(MODULES_CONSOLE)
MODULES += periph/port
SRC=main.c
include $(BSP430_ROOT)/make/Makefile.common