Domanda

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
È stato utile?

Soluzione

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top