This is how is done in msp430gcc:
void Port1Int( void ) __attribute__( ( interrupt( PORT1_VECTOR ) ) ); void Port1Int( void ) { //our isr }
On lauchpad we have one press button that we can use for this task, it's P1.3.
P1DIR &= ~BIT3; // make this pin input P1REN |= BIT3; // turn on internal pull resistor P1OUT |= BIT3; // make pulling up to VCC P1IES |= BIT3; // high to low transition fires interrupt P1IFG &= ~BIT3; // clear interrupt
We have to use internal pull resistor because in newer launchpads there is no resistor for push button. There is a place for one but they removed it probably to lower power consumption.
Let's use timer A0 for some led blinking, here is our setup:
TA0CTL = TASSEL_2 | ID_2 | MC_1; TA0CCR0 = 250000; TA0CCTL0 = CCIE;TASSEL_2 - set clock source for timer to SMCLK which is ~1MHz ID_3 - divide our source clock by /4 MC_1 - counting until we reach value in TACCR0 CCIE - enable compare interrupt
We want to have times around 1s so we divide clock to 1MHz/4 = 250 KHz, so our timer will count 250 000 times per second, it's still pretty fast. So, next we use compare register which will compare our timer value to it and when it's equal it's fire interrupt (CCIE). We compare to 25 000 value so our timer count to this value every 1/10 of second, so we have interrupt 10 times per second.
Let's use all this to make program which starts blinking after pressing push button.
#include#include uint16_t counter = 0; uint8_t second = 0; int main() { WDTCTL = WDTPW + WDTHOLD; BCSCTL1 = CALBC1_1MHZ; DCOCTL = CALDCO_1MHZ; TA0CCR0 = 25000; TA0CCTL0 = CCIE ; P1DIR &= ~BIT3; P1REN |= BIT3; P1OUT |= BIT3; P1IES |= BIT3; P1IFG &= ~BIT3; P1IE |= BIT3; P1DIR |= BIT0 | BIT6; P1OUT &= ~( BIT0 | BIT6 ); __bis_SR_register( GIE ); while(1) { } return 0; } void Port1Int( void ) __attribute__( ( interrupt( PORT1_VECTOR ) ) ); void Port1Int( void ) { switch(P1IFG&BIT3) { case BIT3: P1IFG &= ~BIT3; TA0CTL = TASSEL_2 | ID_2 | MC_1; //run timer break; } } void TimerA0Int( void ) __attribute__( ( interrupt( TIMER0_A0_VECTOR ) ) ); void TimerA0Int( void ) { P1OUT ^= BIT6; if ( counter == 5 ) { counter = 0; second++; P1OUT ^= BIT0; if ( second > 7 ) { TA0CTL = 0; //stop timer second = 0; } } counter++; }
17 - 22 - setting BIT3 PORT1 interrupt
24,25 - setting pins to drive led
26 - this is msp430gcc macro which handle Special Register, here we enable General interrupt enable. When set, enable maskable interrupts ( all except nmi interrupt )
28 - just do nothing and wait for interrupts.
36 - we use switch so we can handle more pins in future
38 - this is important we must clear this bit by software, so we won't renter interrupt again. Normally when there is one interrupt source it's cleared automatically but here we want to check which pin invoke interrupt.
39 - We start our timer so leds will start blinking
44 - It is isr for our timer compare interrupt. One led blinks fast another slower, we blink 7 second and then stopping timer.
Uff, I never thought writing tech blog is so time-consuming and hard. I think my explanation of interrupts and timers is very superficial so don't hesitate and ask question so i can explain more.