【问题标题】:Real time clock , MSP430实时时钟,MSP430
【发布时间】:2011-08-31 04:46:09
【问题描述】:

我需要每 15 分钟设置一次闹钟(00:15、00:30、00:45、01:00,...) 使用实时时钟做一些处理,然后设置新的警报值。 好吧,我已经编写了代码,它可以很好地运行时钟。但不会出现经期警报。

如果有关于代码的反馈会很棒

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

【问题讨论】:

  • 您需要解决您的问题。提供代码很好,但您并不总是提供足够的信息。例如,您使用的是哪个 MSP430 部件?您的代码不完整,因此尽管这里可能有有限的人可以帮助您,但您通过不提供完整(最少)的工作代码来进一步限制它。当它是直接影响RTC警报的部分时,您没有提及您的“计时器”变量具有什么值。您有一个函数 get_fix() 可能会影响问题,但您没有显示它的作用。
  • 我假设您使用的是 MSP430F5XXX 系列器件。如果您使用的是第一代 F5 设备(非 A 变体),那么您必须非常小心,因为硬件有问题。 TI 提供的驱动程序(在我的应用程序中)对于黄金时段来说不够强大。
  • @tinman ,感谢您的反馈,对于给您带来的不便,我们深表歉意。 get_fix() 只是打开GPS_module,这样你就不用担心了。 timer 是时间间隔的全局变量,根据用户的方便而变化
  • @lan 感谢您向我更新有关 F5XXX 严重的信息

标签: c msp430


【解决方案1】:

至少您需要设置 RTCAMIN 寄存器中的 AE 位,以便在分钟匹配时发出警报:

RTCAMIN = AE | (timer & 0x7F);

您似乎还选择了在每分钟更改时发生事件中断(“RTCCTL01 = RTCMODE + RTCTEVIE + RTCTEV_0;”),这与您似乎想要使用的用户可编程警报不同.需要设置报警中断位:

RTCCTL01 = RTCMODE + RTCTAIE;

您增加计时器值的方法不正确,因为它每次都会加倍,而不是增加 15 分钟。你应该在你的 ISR 中使用它:

timer += 15;

如果此周期需要更改,那么您将需要两个变量,一个用于存储新的计时器值,另一个用于存储警报的周期。您可以使用寄存器来存储定时器值,所以它会是这样的(假设“定时器”是用户想要的警报周期):

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

当计时器达到 60 时,您应该将计时器重新设置为 0,而不是 1,否则您的闹钟将在 xx:00:xx xx:15:xx xx:30:xx xx:45:xx xx:01 响起:xx xx:16:xx 等

您不应在计时器变量中精确比较 60 分钟。这无关紧要,但如果使用上面的其他两个错误,您将永远不会在第二次迭代中得到正好 60。此外,如果 60 不能完全被您的警报周期整除,那么您将超过 60 并且需要减少它而不是将其设置为特定值以保持正确的时间。为了更安全,您应该这样做:

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

最后,数据表说您应该在修改警报值时禁用警报中断标志。记得在你的 ISR 中这样做。

其他需要检查的事项是:

  • 确保您没有进入阻止 RTC 更新的低功耗模式
  • 您为组合寄存器 RTCCTL01 使用了正确的定义,并且没有将它们与用于单个寄存器 (RTCCTL0) 的定义混合在一起

我无法判断中断是否正确(看起来应该如此),因为您还没有告诉我们部件号是什么。

【讨论】:

  • @tinman 我做了你建议的改变。但似乎 ISR 从未被任何 IE 调用。我认为 ISR 函数的名称是错误的,所以我使用了#pragma vector=RTC_VECTOR __interrupt void RTC_ISR(void),但事情没有改变....我尝试启用所有中断进行测试,但仍然没有调用 ISR
  • @Abhay:我已经更新了我的答案以包含警报中断位。 “所有中断”是什么意思?所有的 RTC 中断?您是否启用了全局中断(即在状态寄存器中设置 GIE 位)?
  • 我想这可能有助于解决中断 00h 无中断挂起 02h RTC 就绪 RTCRDYIFG 最高 04h RTC 间隔定时器 RTCTEVIFG 06h RTC 用户警报 RTCAIFG 08h RTC 预分频器 0 RT0PSIFG 0Ah RTC 预分频器 1 RT1PSIFG 0Ch RTC 振荡器故障 RTCOFIFG 0Eh 保留最低
  • __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:它看起来是正确的,所以我不知道如果您正确设置了其他所有内容,它为什么不起作用。
猜你喜欢
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-03
  • 2017-01-31
相关资源
最近更新 更多