Jump to content
43oh

Taiko

Members
  • Content Count

    1
  • Joined

  • Last visited

Reputation Activity

  1. Like
    Taiko reacted to Rickta59 in Problem with interrupts on P1 and a timer   
    Here is a follow up to the original post that is focused on trying to use the framework and stay in LPM4 as much as possible
     
    -rick
     
     
     
    File: LPM_Button.ino

    /** * LPM_Button - simple button handler with sleep features * * Demonstrates how to sleep in LPM4 and have port interrupt wake up on button push, * switch to LPM3 run for a bit and then go back to LPM4 from interrupts. */ typedef unsigned int (*uintFuncPtr)(void); /* forward declarations */ void attachInterrupt2(uint8_t, uintFuncPtr, int); unsigned int handleButton(void); /* * -- G L O B A L V A R I A B L E S -- */ unsigned char count = 0; volatile unsigned char times = 0; /* * setup() - Configure pins, disable WDT, assign Pushbutton (p1.3) interrupt handler */ void setup() { disableWatchDog(); // disable timer keeper to use less power pinMode(RED_LED,OUTPUT); pinMode(GREEN_LED,OUTPUT); pinMode(PUSH2, INPUT_PULLUP); digitalWrite(RED_LED, HIGH); digitalWrite(GREEN_LED, LOW); attachInterrupt2(PUSH2, handleButton, RISING); } void loop() { LPM4; // start in ultra low power mode, all work is done in the ISR routines } /* * handleButton() - interrupt handler for button up (low -> high) event */ unsigned int handleButton(void) { ++times; P1OUT |= digital_pin_to_bit_mask[RED_LED]; P1OUT &= ~digital_pin_to_bit_mask[GREEN_LED]; // Set up Timer A "Up to CCR0" mode, divide by 2^n, clock from SMCLK (2)/ACLK (1), clear timer TACCR0 = 0x1fff; TACCTL0 = CCIE; TACTL = MC_1 | ID_0 | TASSEL_1 | TACLR; return OSCOFF; // switch from LPM4 to LPM3 so the ACLK can drive the Timer clock } /* * TA0_ISR() - Handle CCR0 interrupt * in LPM3 mode, blink the lights and then go back to deep sleep */ __attribute__((interrupt(TIMER0_A0_VECTOR))) static void TA0_ISR(void) { if (++count > 2 * times) { P1OUT |= digital_pin_to_bit_mask[RED_LED]; P1OUT &= ~digital_pin_to_bit_mask[GREEN_LED]; TACTL = TACLR; __bis_status_register_on_exit(OSCOFF); // switch back back into LPM4 sleep } else { P1OUT ^= digital_pin_to_bit_mask[RED_LED]|digital_pin_to_bit_mask[GREEN_LED]; } }
    File: WInterrupt2.ino

    /* * WInterrupt2.ino - interrupt handlers with LPM modification * * Functions that provide a way for user written PORTN interrupt handlers to clear bits * in the SR register of an ISR so the MCU can switch sleep modes. The user written * handlers should return 0 or an unsigned LPM modebit value(s) to clear on ISR exit. * * Based on WInterrupts.cpp * * Author: Rick Kimball <rick@kimballsoftware.com> */ #define bit_pos(A) ((A) == 1u << 0 ? 0 \ : (A) == 1u << 1 ? 1 \ : (A) == 1u << 2 ? 2 \ : (A) == 1u << 3 ? 3 \ : (A) == 1u << 4 ? 4 \ : (A) == 1u << 5 ? 5 \ : (A) == 1u << 6 ? 6 \ : (A) == 1u << 7 ? 7 \ : 0) typedef unsigned int (*uintFuncPtr)(void); #define NUM_INTS_PER_PORT 8 static volatile uintFuncPtr intFuncP1[NUM_INTS_PER_PORT]; #if defined(__MSP430_HAS_PORT2_R__) static volatile uintFuncPtr intFuncP2[NUM_INTS_PER_PORT]; #endif /** * attachInterrupt2 - assign a user defined function to a port interrupt pin */ void attachInterrupt2(uint8_t interruptNum, unsigned int (*userFunc)(void), int mode) { uint8_t bit = digitalPinToBitMask(interruptNum); uint8_t port = digitalPinToPort(interruptNum); if ((port == NOT_A_PIN) || !((mode == FALLING) || (mode == RISING))) return; __dint(); switch(port) { case P1: P1IE |= bit; P1IFG &= ~bit; P1IES = mode ? P1IES | bit : P1IES & ~bit; intFuncP1[bit_pos(bit)] = userFunc; break; #if defined(__MSP430_HAS_PORT2_R__) case P2: P2IE |= bit; P2IFG &= bit; P2IES = mode ? P2IES | bit : P2IES & ~bit; intFuncP2[bit_pos(bit)] = userFunc; break; #endif default: break; } __eint(); } void detachInterrupt2(uint8_t interruptNum) { uint8_t bit = digitalPinToBitMask(interruptNum); uint8_t port = digitalPinToPort(interruptNum); if (port == NOT_A_PIN) return; switch(port) { case P1: P1IE &= ~bit; intFuncP1[bit_pos(bit)] = 0; break; #if defined(__MSP430_HAS_PORT2_R__) case P2: P2IE &= ~bit; intFuncP2[bit_pos(bit)] = 0; break; #endif default: break; } } __attribute__((interrupt(PORT1_VECTOR))) void Port_1(void) { uint8_t i; for(i = 0; i < 8; i++) { if((P1IFG & BV(i)) && intFuncP1[i]) { unsigned bits2clear; if ( bits2clear=intFuncP1[i]() ) { __bic_status_register_on_exit(bits2clear); } P1IFG &= ~BV(i); } } } #if defined(__MSP430_HAS_PORT2_R__) __attribute__((interrupt(PORT2_VECTOR))) void Port_2(void) { uint8_t i; for(i = 0; i < 8; i++) { if((P2IFG & BV(i)) && intFuncP2[i]) { unsigned bits2clear; if ( bits2clear=intFuncP2[i]() ) { __bic_status_register_on_exit(bits2clear); } P2IFG &= ~BV(i); } } } #endif
×
×
  • Create New...