I have two projects right how that are using the MSP430 low power modes. I understand the need to put the part to sleep, but don't understand the need to clear the bit after there has been an interrupt.
I've noticed a few things so far. I can only use LPM0 if I want to receive UART messages at 115200 because the low frequency oscillator is too slow. I also have to purposely exit/clear the LPM0 bit in the I2C interrupt routine in order to process them in main.
So I'm really unsure if I have all my code correct. I was hoping someone could review and give any suggestions.
Project 1
// Wake up to process data received over the UART as it comes in. // Wake when I2C slave commands come in and response appropriately. // Also noticed I had to clear the lpm bit in order to wake up from I2C transactions int main(void) { //Stop WDT WDT_A_hold(WDT_A_BASE); initClockTo16MHz(); initUART(0); initGPIO(); initI2C(); while(1) { if(rxFlag == 1) { processUART(); } __bis_SR_register(LPM0_bits + GIE); } } // UART Interrupt #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=USCI_A0_VECTOR __interrupt void USCI_A0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_A0_VECTOR))) USCI_A0_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(UCA0IV,USCI_UART_UCTXCPTIFG)) { case USCI_NONE: break; case USCI_UART_UCRXIFG: UCA0IFG &=~ UCRXIFG; // Clear interrupt rxData = UCA0RXBUF; rxFlag = 1; __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti break; case USCI_UART_UCTXIFG: break; case USCI_UART_UCSTTIFG: break; case USCI_UART_UCTXCPTIFG: break; } } //****************************************************************************** // I2C Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { //Must read from UCB0RXBUF uint8_t rx_val = 0; switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG break; case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: UCB0IFG &= ~(UCTXIFG0); break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2 case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2 case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 rx_val = UCB0RXBUF; switch (SlaveMode) { case (RX_REG_ADDRESS_MODE): ReceiveRegAddr = rx_val; I2C_Slave_ProcessCMD(ReceiveRegAddr); break; case (RX_DATA_MODE): ReceiveBuffer[ReceiveIndex++] = rx_val; RXByteCtr--; if (RXByteCtr == 0) { //Done Receiving MSG SlaveMode = RX_REG_ADDRESS_MODE; UCB0IE &= ~(UCTXIE); UCB0IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti } break; default: __no_operation(); break; } break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 UCB0TXBUF = TransmitBuffer[TransmitIndex++]; TXByteCtr--; if (TXByteCtr == 0) { //Done Transmitting MSG SlaveMode = TX_REG_ADDRESS_MODE; UCB0IE &= ~(UCTXIE); UCB0IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); } break; // Interrupt Vector: I2C Mode: UCTXIFG default: break; } }
Project 2
int main(void) { //Stop WDT WDT_A_hold(WDT_A_BASE); initClockTo16MHz(); initUART(); /* Initialize peripherals */ initGPIO(); initPWM(); initI2C(); initRTC(); while(1) { currentSample(); led_current_reading = ADC_Conversion_Result; tempSample(); current_temp_reading = ADC_Conversion_Result; doOtherStuff(); //LPM3, RTC or I2C will force exit __bis_SR_register(LPM3_bits + GIE); } } void currentSample(void) { enable_ADC10(ADCINCH_0); __delay_cycles(15); //Enable and Start the conversion //in Single-Channel, Single Conversion Mode ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL); //LPM3, ADC conversion complete will force exit __bis_SR_register(LPM0_bits + GIE); disable_ADC10(); } void tempSample(void) { enable_ADC10(ADCINCH_12); __delay_cycles(15); //Enable and Start the conversion //in Single-Channel, Single Conversion Mode ADC_startConversion(ADC_BASE, ADC_SINGLECHANNEL); //LPM3, ADC conversion complete will force exit __bis_SR_register(LPM0_bits + GIE); disable_ADC10(); } void disable_ADC10(void){ ADC_disableConversions(ADC_BASE,0); ADC_disable(ADC_BASE); } void enable_ADC10(uint8_t adc_channel){ //Initialize the ADC Module ADC_init(ADC_BASE, ADC_SAMPLEHOLDSOURCE_SC, ADC_CLOCKSOURCE_ADCOSC, ADC_CLOCKDIVIDER_1); ADC_enable(ADC_BASE); ADC_setupSamplingTimer(ADC_BASE, ADC_CYCLEHOLD_1024_CYCLES, ADC_MULTIPLESAMPLESDISABLE); if(adc_channel == ADCINCH_12) { ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_INT, ADC_VREFNEG_AVSS); } else { ADC_configureMemory(ADC_BASE, adc_channel, ADC_VREFPOS_AVCC, ADC_VREFNEG_AVSS); // channel mis-map for A1 in driverlib? } ADC_clearInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT); //Enable the Memory Buffer Interrupt ADC_enableInterrupt(ADC_BASE, ADC_COMPLETED_INTERRUPT); } // ADC interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=ADC_VECTOR __interrupt void ADC_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(ADC_VECTOR))) ADC_ISR (void) #else #error Compiler not supported! #endif { ADC_Conversion_Result = ADCMEM0; __bic_SR_register_on_exit(LPM3_bits); // Sleep Timer Exits LPM3 } // RTC interrupt service routine #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(RTC_VECTOR))) RTC_ISR (void) #else #error Compiler not supported! #endif { __bic_SR_register_on_exit(LPM3_bits); // Timer Exits LPM3 switch(__even_in_range(RTCIV,RTCIV_RTCIF)) { case RTCIV_NONE: break; // No interrupt case RTCIV_RTCIF: // RTC Overflow P2OUT ^= BIT3; break; default: break; } } //****************************************************************************** // I2C Interrupt *************************************************************** //****************************************************************************** #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = USCI_B0_VECTOR __interrupt void USCI_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) USCI_B0_ISR (void) #else #error Compiler not supported! #endif { //Must read from UCB0RXBUF uint8_t rx_val = 0; switch(__even_in_range(UCB0IV, USCI_I2C_UCBIT9IFG)) { case USCI_NONE: break; // Vector 0: No interrupts case USCI_I2C_UCALIFG: break; // Vector 2: ALIFG case USCI_I2C_UCNACKIFG: // Vector 4: NACKIFG break; case USCI_I2C_UCSTTIFG: break; // Vector 6: STTIFG case USCI_I2C_UCSTPIFG: UCB0IFG &= ~(UCTXIFG0); break; // Vector 8: STPIFG case USCI_I2C_UCRXIFG3: break; // Vector 10: RXIFG3 case USCI_I2C_UCTXIFG3: break; // Vector 12: TXIFG3 case USCI_I2C_UCRXIFG2: break; // Vector 14: RXIFG2 case USCI_I2C_UCTXIFG2: break; // Vector 16: TXIFG2 case USCI_I2C_UCRXIFG1: break; // Vector 18: RXIFG1 case USCI_I2C_UCTXIFG1: break; // Vector 20: TXIFG1 case USCI_I2C_UCRXIFG0: // Vector 22: RXIFG0 rx_val = UCB0RXBUF; switch (SlaveMode) { case (RX_REG_ADDRESS_MODE): ReceiveRegAddr = rx_val; I2C_Slave_ProcessCMD(ReceiveRegAddr); / break; case (RX_DATA_MODE): ReceiveBuffer[ReceiveIndex++] = rx_val; RXByteCtr--; if (RXByteCtr == 0) { //Done Receiving MSG SlaveMode = RX_REG_ADDRESS_MODE; UCB0IE &= ~(UCTXIE); UCB0IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); // SHOULD WE DO THIS HERE? __bic_SR_register_on_exit(LPM0_bits); // Exit LPM0 on reti } break; default: __no_operation(); break; } break; case USCI_I2C_UCTXIFG0: // Vector 24: TXIFG0 UCB0TXBUF = TransmitBuffer[TransmitIndex++]; TXByteCtr--; if (TXByteCtr == 0) { //Done Transmitting MSG SlaveMode = TX_REG_ADDRESS_MODE; UCB0IE &= ~(UCTXIE); UCB0IE |= UCRXIE; // Enable RX interrupt I2C_Slave_TransactionDone(ReceiveRegAddr); } break; // Interrupt Vector: I2C Mode: UCTXIFG default: break; } }