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.

CCS/MSP430F6638: MSP430F6638 : RTC_B alarm interrupt doesn't work

Part Number: MSP430F6638

Tool/software: Code Composer Studio

Hello,

I am using msp430f6638 and would like to use the RTC_B module. I have a program and I want at the end of this program to wait 5 min before running again the program. In other words I need at the end of my program the MCU to wait 5 min before running automaticaly once again the program. So for that I tried to write some code where I have a flag which is set to 1 when the alarm interrupt is set and then testing in my program if this flag is set before running it. I have first configured the RTC based on TI example for f6638. Then I have written a really basic code to test the RTC. I just increment a variable "i" each time the interrupt alarm flag is set which occurs when the MCU has finished his 5 min waiting time. Here is the whole code.

#define MASK_MIN_L          0x0F
#define MASK_MIN_H          0xF0
#define MIN_L_MAX           9
#define MIN_H_MAX           0xD0          // 13 and not 5 because alarm enable bit which is bit 7 should always be 1


int main(void)
{

    WDTCTL = WDTPW | WDTHOLD;          // stop watchdog timer

    // ************         ACLK   *************************

    P1DIR |= BIT0;                    // ACLK set out to pin
    P1SEL |= BIT0;
    while(BAKCTL & LOCKBAK)         // Unlock XT1 pins for operation
        BAKCTL &= ~(LOCKBAK);
    UCSCTL6&=~XT1OFF;              // turn on XT1
    UCSCTL6&=~XCAP_3;             // 1pF cap knowing that we already have 20 pF external caps (5.16 datasheet p 28)

    // *************      SMCLK *******************************

    P3SEL|= BIT4;                      // Select SMCLK function to source AFE CLK
    P3DIR|= BIT4;                     // Configured as output
    P7SEL |= BIT2+BIT3;              // Port select XT2
    UCSCTL6&=~XT2OFF;               // turn on XT2
    UCSCTL4|=SELS__XT2CLK;         // source ACLK from XT1 and SMCLK from XT2
    //UCSCTL6&=~XT2DRIVE_3;       // 00b so a range of 4 to 8 MHz since the external crystal on XT2 is 8 MHz

    do
    {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG); // Clear XT2,XT1,DCO fault flags

        SFRIFG1 &= ~OFIFG;                                     // Clear fault flags
    }

    while (SFRIFG1&OFIFG);                   // Test oscillator fault flag

    UCSCTL6 &= ~XT2DRIVE0;            // Decrease XT2 Drive according to (UCSCTL6&=~XT2DRIVE_3; also works) // expected frequency
    UCSCTL4 |= SELS_5 + SELM_5;     // SMCLK=MCLK=XT2


    RTC_config();

    __bis_SR_register(GIE);       // Enter LPM3 mode with interrupts
    // enabled
    __no_operation();

    int flag = 0;
    int i =0;

    while(1)
    {
        if (flag==1)
        {
            i++;
            flag=0;
            wait(0x85); // wait 5 min (here we have 8 because of AE bit)
        }

    }

}

#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=RTC_VECTOR
__interrupt void RTCISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(RTC_VECTOR))) RTCISR (void)
#else
#error Compiler not supported!
#endif
{

    while(BAKCTL & LOCKBAK)                    // Unlock backup system
        BAKCTL &= ~(LOCKBAK);

    switch(__even_in_range(RTCIV,14))
    {
    case  0: break;                           // Vector  0:  No interrupt
    case  2:                                  // Vector  2:  RTCRDYIFG

        flag =1;

        break;
    case  4: break;                           // Vector  4:  RTCEVIFG
    case  6: break;                           // Vector  6:  RTCAIFG
    case  8: break;                           // Vector  8:  RT0PSIFG
    case 10: break;                           // Vector 10:  RT1PSIFG
    case 12: break;                           // Vector 12:  RTCOFIFG
    case 14: break;                           // Vector 14:  Reserved
    default: break;
    }
}

void RTC_config(void)
{
    RTCCTL01|=RTCRDYIE + RTCBCD + RTCHOLD + RTCAIE; // BCD mode, RTC hold, enable RTC read ready interrupt

    RTCYEAR = 0x2020;                         // Year = 0x2020
    RTCMON = 0x03;                            // Month = 0x03 = March
    RTCDAY = 0x02;                            // Day = 0x02 = 2nd
    RTCDOW = 0x00;                            // Day of week = 0x00 = Monday
    RTCHOUR = 0x15;                           // Hour = 0x15
    RTCMIN = 0x00;                            // Minute = 0x00
    RTCSEC = 0x00;                            // Seconds = 0x00

    RTCCTL1 &= ~(RTCHOLD);                   // Start RTC calendar mode

}

void wait(unsigned char time)
{
    unsigned char min_l=0;
    unsigned char min_h=0;

    min_l = time & MASK_MIN_L;
    min_h = time & MASK_MIN_H;

    if (min_l>MIN_L_MAX)
    {
        min_l=0;
        min_h++;
    }

    if (min_h>MIN_H_MAX)
    {
        min_h=0x80;
        min_l=0;
    }


    RTCAMIN = min_l|min_h;

    time+= time;

}

So basically the function "wait" has a input which is the time we want the mcu to wait (here 5 min so 0x85). Then in the function I test by applying masks the low and high digit of "time" variable. Then in the RTCAMIN register I put the value of the input thanks to min_l and min_h variables. Finally since I initialize RTCMIN register to 0x00, and I need a first alarm at 15:05 then 15:10, 15:15 etc... at the end of the function I increment "time" by its value so the next time the function is called an alarm will be set at 15:10 if the first one was at 15:05. I hope that the idea is clear. The problem is that this program doesn't work. I mean I never have the interrput set and so "flag" is never set. I really don't see where is the problem and if there is an error in the code above. I have checked all the registers concerned. Everything seems to be ok but it doesn't work.  Any help would be appreciated. 

Thank you,

Best regards,

Mike

  • Could someone help please ?

    Thank you

  • main() and the ISR are referencing two different "flag" variables. (I don't see the declaration for the one the ISR is using, so I don't think this code will even compile.) Move the declaration that's inside main outside and make it "volatile".

    I'm not quite sure I understand the arithmetic in wait(), but I don't think it's doing what you want. I expect you want to take the value of RTCMIN, add "time" to it, and put that into RTCAMIN. Yes, what you have will work the first time since you just initialized RTCMIN=0x00, but it won't scale.

    Unsolicited: wait() will (presumably) always set the AE bit, so have it always do that and don't require the caller to supply it. What you have will probably work  but you're making things more difficult than they need to be.

    You'll also make your life a little easier by not using RTCBCD (and/or using the BIN2BCD register).

  • Hi Bruce,

    Thank you for your answer. 

    "main() and the ISR are referencing two different "flag" variables. (I don't see the declaration for the one the ISR is using, so I don't think this code will even compile.) Move the declaration that's inside main outside and make it "volatile"."

    I didn't get your comment. There is only one flag variable in the program and it's the same flag in the ISR and main() (line 54 and 83). "flag" variable is defined at line 49.

    "I'm not quite sure I understand the arithmetic in wait(), but I don't think it's doing what you want. I expect you want to take the value of RTCMIN, add "time" to it, and put that into RTCAMIN. Yes, what you have will work the first time since you just initialized RTCMIN=0x00, but it won't scale."

    I need an alarm each five minutes. So my idea was to configure for example minutes register to 0x00 then when the function wait() is called (time variable is equal to 5 the first time) at the end of it I increment variable time by its value (which is 5) so the next time wait() is called in the RTCAMIN register we have 10 then the next time 15 then 20 etc... Hope it's clearer now.

    "Unsolicited: wait() will (presumably) always set the AE bit, so have it always do that and don't require the caller to supply it. What you have will probably work  but you're making things more difficult than they need to be."

    I didn't really understand what i'm doing more difficult that it needs to be. AE should always be set to have the minute alarm no ? 

    Thank you,

    Regards,

    Mike

  • The variable ("flag") declared at line 49 is inside main(), and so invisible to RTCISR(). This is how C works. I don't know what "flag" RTCISR is referring to, since this code doesn't compile. If you move line 49 outside main, the compiler will probably tell you where the other one is.

    Similarly, doubling the value of a local variable ("time") just before exiting a function ("wait") doesn't have much effect. This is how C works.

**Attention** This is a public forum