To get started with the MSP430, mspgcc, mspdebug and TI’s Launchpad board, I made a simple metronome. Press the button twice to set the LED period.
Timer0 increments a global tick counter. On button press an interrupt is fired and the current tick count is stored. After two button presses the LED period (in ticks) is stored. The LED is then toggled at this period.
As the MSP430 is all about low power, this could likely be done better with an extra timer and a low power mode. But, still a good exercise.
Download source and Makefile.
/************************************************************
TI Launchpad MSP430 Simple Metronome.
Press button twice to set speed.
Joby Taffey
************************************************************/
#include
#include
/************************************************************/
#define LED_BIT (BIT0 | BIT6) // both LEDs
#define LED_DIR P1DIR
#define LED_OUT P1OUT
#define SWITCH_BIT BIT3
#define SWITCH_DIR P1DIR
#define SWITCH_IE P1IE // interrupt enable
#define SWITCH_ES P1IES // interrupt edge select
/************************************************************/
static volatile uint16_t ticks = 0; // tick counter
static volatile uint16_t lastPressTicks = 0; // tick count of last button press
static volatile uint16_t ledPeriodTicks = 0; // number of ticks between LED flashes
static volatile uint16_t ledTimer = 0; // LED flash downcounter (ledPeriodTicks to 0)
/************************************************************/
// Timer0 ISR
interrupt(TIMERA0_VECTOR) TIMERA0_ISR(void)
{
ticks++;
if (ledPeriodTicks > 0)
{
if (ledTimer > 0)
{
ledTimer--;
}
else
{
ledTimer = ledPeriodTicks;
LED_OUT ^= LED_BIT;
}
}
}
// Port1 ISR
interrupt(PORT1_VECTOR) P1_ISR(void)
{
if((P1IFG & BIT3) == SWITCH_BIT) // switch pressed
{
if (lastPressTicks == 0) // first press
{
lastPressTicks = ticks;
LED_OUT |= LED_BIT; // Turn on LED
}
else
{
ledPeriodTicks = (ticks - lastPressTicks);
ledTimer = ledPeriodTicks;
lastPressTicks = 0;
LED_OUT &= ~LED_BIT; // Turn off LED
}
}
P1IFG = 0x00; // clear interrupt flags
}
/************************************************************/
int main(void)
{
// Stop watchdog timer
WDTCTL = WDTPW + WDTHOLD;
// Set ACLK to use internal VLO (12kHz)
BCSCTL3 |= LFXT1S_2;
// TimerA aux clock in UP mode
TACTL = TASSEL_1 | MC_1;
// Enable interrupt for TACCR0 match
TACCTL0 = CCIE;
// Set TACCR0, starts timer
TACCR0 = 1;
// setup switch interrupt
SWITCH_DIR &= ~SWITCH_BIT; // as input
SWITCH_ES |= 0x01; // interrupt on falling edge
SWITCH_IE |= SWITCH_BIT; // interrupt enable
// Setup LED pins
LED_DIR |= LED_BIT; // Set LED pins as outputs
LED_OUT &= ~LED_BIT; // Turn off both LEDs
// Enable interrupts
eint();
while(1)
{
// everything happens under interrupt
}
return 0;
}