打印

请香主和大侠看下RTC的问题(用官方库)已解决

[复制链接]
3999|19
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zhaoyu2005|  楼主 | 2009-7-20 23:53 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
RTC, TE, TI, ST, se
先贴上中断部分的程序:
void RTC_IRQHandler(void)
{
  vu32 Time_temp;
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_SEC);

    /* Enable time update */
    TimeDisplay = 1;

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    /* Reset RTC Counter when Time is 23:59:59 */
    Time_temp=RTC_GetCounter();
    if (Time_temp >= 0x00015180)      //这部分原来是判断计数器是否等于0x00015180(即86400),如果等于的话,将计数器清零,现在这个是我改的
    {
      Time_temp=Time_temp%0x00015180;
      RTC_SetCounter(Time_temp);
      /* Wait until last write operation on RTC registers has finished */
      RTC_WaitForLastTask();
    }
  }
}

情况是这样的,我在主程序里将时间设置好以后,板子超过一天没上电,再上电时显示40:00:10,我就把中断函数改了下,计算计数器的值除以0x00015180的余数,将余数写回计数器,达到自动修正时间的目的,但是改完后,再次上电就发现程序卡在RTC_WaitForLastTask()这个函数里了,也就是这句while ((RTC->CRL & RTC_FLAG_RTOFF) == (u16)RESET)。
不知道咋会卡到这儿,计数器还在一直计数
沙发
香水城| | 2009-7-22 08:58 | 只看该作者

你这个算法就不对,不应该频繁地复位寄存器

应该以某个绝对时间为基准来进行计算。例如以2009年1月1日0时为基准,如果读出的计数器数值为12345678,则计算如下:
   12345678 / 86400 = 142天+21小时+21分+18秒
再算出月日:
  31+28+31+30+22=142
得出:
   12345678对应2009年5月23日21时21分18秒

使用特权

评论回复
板凳
zhaoyu2005|  楼主 | 2009-7-22 09:36 | 只看该作者

你说的没错,我现在不需要年月日,只显示时间就行

就是每天过了00:00:00再开机,时间显示成问题,不知道咋处理。我参考例程改的。
我明白你的意思,让计数器一直计数,需要时间的话计算出来,但是我认为我的用法应该能支持的,除了设置时间,每天最多修改一次计数器的值,先不说这样好不好,我想知道,想这样用,咋处理能行

使用特权

评论回复
地板
香水城| | 2009-7-22 09:44 | 只看该作者

你安排了00:00:00时中断并复位计数器,但此时CPU不工作

怎么能实现功能?

关于你的问题,怀疑是重新写回时没有写正确。

使用特权

评论回复
5
zhaoyu2005|  楼主 | 2009-7-22 10:15 | 只看该作者

我这个上电后出的问题,不是在后被电池下进行的

你可能没看仔细,我这程序,如果一直加电运行,没问题,过了23:59:59就是00:00:00,但是如果掉电(关机,后备电池供电)了,再开机的话,计数器的值可能超过了86400,需要取余后再写回计数器,这样时间就自动更新了。你以为这样不好,复位寄存器太频繁了,我可以改为——根据一个固定的时间计算,但是运行了一段时间,发现时间不准了,需要重新设置时,还会出同样的问题,我现在想避免初始化外调用RTC_SetCounter(xx)这个函数出问题的情况

使用特权

评论回复
6
lpcfans| | 2009-7-22 10:15 | 只看该作者

这个需要MARK一下。。。

使用特权

评论回复
7
香水城| | 2009-7-22 10:25 | 只看该作者

楼主位的程序有2处RTC_WaitForLastTask()

到底是哪个?

使用特权

评论回复
8
zhaoyu2005|  楼主 | 2009-7-22 10:29 | 只看该作者

最下边那个

就是调用RTC_SetCounter(xx)函数后,再调用RTC_WaitForLastTask()函数就出问题了,之前坛子里也有朋友遇到,不知道咋解决的

使用特权

评论回复
9
香水城| | 2009-7-22 10:52 | 只看该作者

看看手册,这个问题很好解决

请看手册中的这个说明:RTC_WaitForLastTask()函数是在写RTC寄存器之前调用的,写RTC寄存器之后不必调用。更重要的是,再重新上电之后,操作RTC寄存器之前,需要调用一次RTC_WaitForSynchro()函数。

把你的程序修改一下试试。

使用特权

评论回复
10
zhaoyu2005|  楼主 | 2009-7-22 11:05 | 只看该作者

我马上改下试试

请问香主,这个手册的全名是?我没注意过这个手册,刚才翻了下,电脑里没有这个,估计是RTC_WaitForSynchro()造成的。

使用特权

评论回复
11
香水城| | 2009-7-22 11:07 | 只看该作者

安装了最新的V3.1固件库就有:stm32f10x_stdperiph_lib_um.chm

其它版本的固件库也有对应的说明文档,一般在固件库的根目录下。

使用特权

评论回复
12
zhaoyu2005|  楼主 | 2009-7-22 11:25 | 只看该作者

刚才改了下,还是不行

void RTC_IRQHandler(void)
{
  vu32 Time_temp;
  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
  {
    /* Clear the RTC Second interrupt */
    RTC_ClearITPendingBit(RTC_IT_SEC);

    /* Enable time update */
    TimeDisplay = 1;

    /* Wait until last write operation on RTC registers has finished */
    RTC_WaitForLastTask();
    /* Reset RTC Counter when Time is 23:59:59 */
    Time_temp=RTC_GetCounter();
    if (Time_temp >= 0x00015180)
    {
      Time_temp=Time_temp%0x00015180;
      RTC_WaitForLastTask();   //刚加的
      RTC_WaitForSynchro();    //刚加的
      RTC_WaitForLastTask();   //刚加的
      RTC_SetCounter(Time_temp);
      /* Wait until last write operation on RTC registers has finished */
      RTC_WaitForLastTask();
    }
  }
}

我下载到芯片里还是不行,用jlink调试看了下,刚加的三条语句运行正常,还是卡在下边的RTC_WaitForLastTask()函数
顺便说下我现在还是用2.03库

使用特权

评论回复
13
香水城| | 2009-7-22 11:30 | 只看该作者

请仔细看看我在9楼的说明

1)RTC_WaitForLastTask()函数是在写RTC寄存器之前调用
2)更重要的是,再重新上电之后,操作RTC寄存器之前,需要调用一次RTC_WaitForSynchro()函数。

使用特权

评论回复
14
香水城| | 2009-7-22 11:43 | 只看该作者

你的程序是先操作RTC寄存器,再调用RTC_WaitForSynchro()函数

使用特权

评论回复
15
zhaoyu2005|  楼主 | 2009-7-22 12:03 | 只看该作者

看上边大红字,在中断函数开始调用RTC_WaitForSynchro()

我刚才改了,在中断函数开始加了RTC_WaitForSynchro(),还是卡在RTC_WaitForLastTask();
不好意思,麻烦你了

使用特权

评论回复
16
magic_yang| | 2009-7-22 13:52 | 只看该作者

我的也卡在这里了 真的很郁闷

我的问题跟他的一样, 看来真的郁闷, ST的能不能给个好的解决办法叫人无言

使用特权

评论回复
17
香水城| | 2009-7-22 14:27 | 只看该作者

楼主出来说说如何解决的

不要就改一下标题就完了。

使用特权

评论回复
18
zhaoyu2005|  楼主 | 2009-7-22 14:27 | 只看该作者

经过不懈努力,终于好了

问题应该是出在
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  PWR_BackupAccessCmd(ENABLE);
这两个函数上
在参考手册里找到了说明:上电复位后,RTC和备份寄存器出于写保护状态,同时PWR和BKP的时钟处于关闭状态
所以要修改RTC的数据,必须解除写保护,同时启用PWR和BKP的时钟

使用特权

评论回复
19
zhaoyu2005|  楼主 | 2009-7-22 14:29 | 只看该作者

刚才忘了,谢谢香主的大力帮助

同时请新手注意下这个问题

使用特权

评论回复
20
zhaoyu2005|  楼主 | 2009-7-22 15:25 | 只看该作者

上面说的有不严谨

应该是先打开PWR和BKP的时钟,再解除写保护,顺序反了不行:没有时钟,当然也就不能解除写保护了,出这问题主要因为技术参考手册没有仔细看,希望其他友人引以为戒

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

78

主题

2940

帖子

9

粉丝