3

I need to set an alarm every 15 minutes (00:15, 00:30, 00:45, 01:00, ...) using a Real time clock do some process and then set new alarm value. Well I have a written the code, it does well to run the clock. But no period alarms occur.

It would be great to have feedback on the code

void rtc_init(void)
{
  RTCCTL01 = RTCMODE + RTCTEVIE + RTCTEV_0;
  RTCCTL01 |= RTCHOLD;
  RTCSEC =  0x00;                       
  RTCMIN =  0x28;                       
  RTCHOUR = 0x12;                       
  RTCDOW =  0x05;                       
  RTCDAY =  0x1A;                       
  RTCMON =  0x08;                      
  RTCYEAR = 0x07DB;                    
  RTCAMIN = timer;
  RTCCTL01 &= ~RTCHOLD;
  __enable_interrupt();
}

#pragma vector=RTC_VECTOR

__interrupt void handle_rtc_interrupt(void)
{
    switch(__even_in_range(RTCIV,8))
    {                
    case 6:
           get_fix();
           timer += timer;
           if (timer == 60) timer = 1;
           RTCAMIN = timer;
           RTCCTL1 &= ~RTCHOLD;
           break;
    }//switch
}//ISR
wallyk
  • 56,922
  • 16
  • 83
  • 148
Abhay
  • 85
  • 3
  • 10
  • 3
    You need to work on your questions. It is good that you are providing code, but you do not always provide enough information. For example, what MSP430 part are you using? Your code is incomplete, so although there are probably a limited number of people here that could help you, you are further limiting it by not providing a complete (minimal) working code. You do not mention what value your "timer" variable has, when it is the part which directly affects the RTC alarm. You have a function get_fix() which could be affecting the problem but you do not show what it does. – tinman Aug 30 '11 at 09:50
  • I assume that you are using the MSP430F5XXX series devices. If you are using one of the first generation F5 devices (non-A variants) then you must be very careful as the hardware is buggy. The TI supplied driver was not (in my application) robust enough for prime time. – uɐɪ Aug 30 '11 at 11:41
  • @tinman , thank for the feedback and sorry for any inconvenience. `get_fix()` is just about switching ON the `GPS_module` so you can be least worried about it. `timer` is a global variable for time interval, which changes as per user convenience – Abhay Aug 30 '11 at 16:45
  • @lan thanks for updating me about F5XXX serious – Abhay Aug 30 '11 at 16:45

1 Answers1

2

At the very least you need to set the AE bit in the RTCAMIN register for the alarm to go off when the minutes match:

RTCAMIN = AE | (timer & 0x7F);

It also looks like you have the event interrupt selected to occur on every change of a minute ("RTCCTL01 = RTCMODE + RTCTEVIE + RTCTEV_0;") which is not the same as the user programmable alarm that you seem to want to use. You need to set the alarm interrupt bits:

RTCCTL01 = RTCMODE + RTCTAIE;

Your method of incrementing the timer value is incorrect as it will double each time, not go up by 15 minutes. Your should use this in your ISR:

timer += 15;

If this period needs to change then you will need two variables, one to store the new timer value and one to store the period of the alarms. You could use the register to store the timer value, so it would be something like this (assuming "timer" is the period of the alarm that the user wants):

next_timer = RTCAMIN & 0x7F;
next_timer += timer;
if (next_timer) >= 60
{
    next_timer -= 60;
}
RTCAMIN = AE | (next_timer & 0x7F);

You should re-set the timer to 0, not 1, when it reaches 60 otherwise your alarms will go off at xx:00:xx xx:15:xx xx:30:xx xx:45:xx xx:01:xx xx:16:xx etc.

You should not compare exactly for 60 minutes in your timer variable. It does not matter so much, but with the other two bugs above you would never have gotten exactly 60 on the second iteration. Also if 60 is not exactly divisible by your alarm period then you will go past 60 and need to reduce it rather than set it to a specific value to maintain the correct timing. You should do this to be safer:

if (timer >= 60) timer -= 60;

Finally, the datasheet says you should disable the alarm interrupt flags while modifying the alarm values. Remember to do that in your ISR.

Other things to check are:

  • ensure you are not going into a low power mode that stops the RTC from updating
  • you've used the correct definitions for the combined register RTCCTL01 and not mixed them with definitions that are meant for the individual registers (RTCCTL0)

I cannot tell whether the interrupt is the correct one (it looks like it should be) as you've still not told us what the part number is.

tinman
  • 6,348
  • 1
  • 30
  • 43
  • *@tinman* i made the changes you had suggested. But it seems like the ISR never gets called for any IE. I thought the name of ISR function was wrong , so i used `#pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void)` but things don change .... I tried enabling all interrupts to test but still the ISR is not called – Abhay Aug 30 '11 at 18:59
  • @Abhay: I've updated my answer to include the alarm interrupt bits. What do you mean by "all interrupts"? All of the RTC interrupts? Did you enable interrupts globally (i.e. setting GIE bit in status register)? – tinman Aug 30 '11 at 20:48
  • I guess this might help about the interrupts 00h No interrupt pending 02h RTC ready RTCRDYIFG Highest 04h RTC interval timer RTCTEVIFG 06h RTC user alarm RTCAIFG 08h RTC prescaler 0 RT0PSIFG 0Ah RTC prescaler 1 RT1PSIFG 0Ch RTC oscillator failure RTCOFIFG 0Eh Reserved Lowest – Abhay Aug 30 '11 at 21:25
  • 1
    `__interrupt void handle_rtc_interrupt(void) { volatile unsigned int next_timer; switch(__even_in_range(RTCIV,8)) { case 6:{ RTCCTL0 &= ~RTCAIFG; RTCAMIN |= 0x00; get_fix(); next_timer = RTCAMIN & 0x7F; next_timer += timer; if (next_timer >= 60); { next_timer -= 60; } RTCAMIN = 0x80 | (next_timer & 0x7F); RTCCTL0 |= RTCAIE; RTCCTL01 &= ~RTCHOLD; break; } } }//ISR` – Abhay Aug 30 '11 at 21:43
  • @Abhay: It looks correct, so I don't know why it wouldn't work if you've set everything else up correctly. – tinman Aug 31 '11 at 13:14