This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hello, and thank you for taking the time to read my issue.
I've written a program that is using both timer B0 and the RTC. While the main body is active, the B0 timer is suppose just flashing an led at 1 sec intervals. I threw in a while loop to hold the system active for 10 seconds. After it exits the hold, it will then disable timer_B0, and enable the RTC. I then enable low power mode and it sleeps for 11 seconds. Once it exits low power mode, the RTC is disabled and the Timer_B0 is re-enabled. and it repeats.
#include <msp430.h> void initGpio(void); unsigned int iiiii; unsigned int my_seconds; int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop WDT my_seconds = 0; initGpio(); // Configure GPIO // Initialize XT1 32kHz crystal P2SEL1 |= BIT6 | BIT7; // P2.6~P2.7: crystal pins do { CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag SFRIFG1 &= ~OFIFG; } while (SFRIFG1 & OFIFG); // Test oscillator fault flag __enable_interrupt(); // The RTC interrupt should trigger now... RTCMOD = (10*32)-1; RTCCTL = RTCSS_2 | RTCSR | RTCPS_7; // Configure Timer_A TB0CTL = TBSSEL_1 | CNTL_1 | MC_2 | ID_3 | TBCLR | TBIE; // ACLK, count mode, clear TBR, enable interrupt while(1) { iiiii = 0; while (iiiii < 10) {} TB0CTL &= ~TBIE; P1OUT &= ~BIT0; RTCCTL |= RTCSR | RTCIE; P6OUT &= ~BIT6; _bis_SR_register(LPM3_bits| GIE); RTCCTL &= ~RTCIE; TB0CTL |= TBIE | TBCLR; } } void initGpio(void) { P1DIR = 0xFF; P2DIR = 0xFF; P6DIR = 0xFF; P1REN = 0xFF; P2REN = 0xFF; P1OUT = 0x00; P2OUT = 0x00; P6OUT = 0x00; // Configure GPIO P1DIR |= BIT0; P1OUT |= BIT0; P6DIR |= BIT6; P6OUT |= BIT6; // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings PM5CTL0 &= ~LOCKLPM5; } // Timer0_B3 Interrupt Vector (TBIV) handler #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=TIMER0_B1_VECTOR __interrupt void TIMER0_B1_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(TIMER0_B1_VECTOR))) TIMER0_B1_ISR (void) #else #error Compiler not supported! #endif { switch(__even_in_range(TB0IV,TB0IV_TBIFG)) { case TB0IV_NONE: break; // No interrupt case TB0IV_TBCCR1: break; // CCR1 not used case TB0IV_TBCCR2: break; // CCR2 not used case TB0IV_TBIFG: P1OUT ^= BIT0; // overflow iiiii++; my_seconds++; break; default: break; } } #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 { switch(__even_in_range(RTCIV, RTCIV_RTCIF)) { case RTCIV_NONE : break; // No interrupt pending case RTCIV_RTCIF: // RTC Overflow // Toggle LED on P1.0 P6OUT ^= BIT6; //TB0CTL ^= TBIE; // Store P1OUT value in backup memory register *(unsigned int *)BKMEM_BASE = P1OUT; _low_power_mode_off_on_exit(); break; default: break; } }
Here is the issue, the above code was just my test for implementing the dual timer, enable disable process. I've moved over the code to my actual program and what I'm seeing is after I exit the low power mode the first time, which works correct, my system re-enables timer_b0 and counts just fine, but when its time to enter lowpowermode, it jumps immediately to the ISR. No delay.
I checked the registers, and RTCMOD is still showing 15F (351 or 11 seconds). There is no difference between the registers before and after the first time it enters lpm.
before first LPM
after first lpm
As long as RTCSS is non-zero the RTC will continue to count. As it happens, your RTC cycle is the same as your TB0-ten-times cycle, so RTCIFG (as seen in your register dump) is already set when you set RTCIE.
TB0 is also still counting (since you haven't set MC=0) all the time, but the effect of that is probably less visible.
Bruce,
Hello again!!
>>TB0 is also still counting (since you haven't set MC=0) all the time, but the effect of that is probably less visible.
yep as I was researching this i made note that I needed to change MC=0, so that I wasn't eating up energy while I was sleeping. Another aspect of this is saving as much energy as possible. But it just completely slipped my mind. Thank you for point that out!!
>>As long as RTCSS is non-zero the RTC will continue to count. As it happens, your RTC cycle is the same as your TB0-ten-times cycle, so RTCIFG (as seen >>in your register dump) is already set when you set RTCIE.
Ok, so if I'm understanding correctly.
even though I am doing
RTCCTL |= RTCSR | RTCIE;
I am obviously enabling the interrupt, but more importantly I thought that RTCSR was resetting the counter. per the documentation
RTCCNT is cleared by the overflow event, or it can be reset by software writing logic 1 to the RTCSR bit in the RTCCTL register.
In any case, I made these changes
TB0CTL &= ~TBIE; TB0CTL &= ~MC_2; //setting MC=0 P1OUT &= ~BIT0; RTCCTL |= RTCSR | RTCIE | RTCSS_2; //setting RTCSS to XT1CLK P6OUT &= ~BIT6; _bis_SR_register(LPM3_bits| GIE); RTCCTL &= ~RTCIE; RTCCTL &= ~RTCSS_2; //setting RTCSS to no clock TB0CTL |= TBIE | TBCLR | MC_2; //Setting MC=2
It now appears to be working just fine. Again, thank you for the support!!!!
But RTCSR doesn't clear RTCIFG, which is what I expect you are (were) encountering.
Also, the RTCCNT clear operation takes one XT1CLK cycle (~30us) which is probably long enough to create an illusion in your register dump.
Anyway, I'm glad you got it working.
**Attention** This is a public forum