打印
[STM32F1]

stm32f103 RTC计数器更新的问题

[复制链接]
6078|6
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
pofu007|  楼主 | 2014-7-25 15:44 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
RTC初始化的时候调用库函数RTC_SetCounter( )没有问题(初始化代码如下所示)。RTC初始化后,重新设置当前时间,再去调用RTC_SetCounter( )时,就在RTC_WaitForLastTask()中就跳不出来了。

百度了一下有人说如下处理,果然有效,可是不知道原因,还望了解真相的告知一二!
RTC_WaitForLastTask();
RTC_SetCounter(counter);        // 设置RTC计数器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_WaitForLastTask();

初始化代码
RTC_NVIC_Config();
RCC_APB1PeriphClockCmd((RCC_APB1Periph_PWR | RCC_APB1Periph_BKP), ENABLE);        // 使能PWR和BKR时钟
PWR_BackupAccessCmd(ENABLE);        // 使能BKR访问
BKP_DeInit();        // 复位BKR寄存器内容
               
RCC_LSEConfig(RCC_LSE_ON);        // 使能LSE
while(RESET == RCC_GetFlagStatus(RCC_FLAG_LSERDY))        // 等待LSE稳定
{
        delay_ms(10);
}
               
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);        // 选择LSE作为RTC模块时钟源
RCC_RTCCLKCmd(ENABLE);        // 使能RTC时钟
               
RTC_WaitForLastTask();        // 等待RTC最近一次寄存器写操作完成
RTC_WaitForSynchro();        // 等待RTC寄存器同步完成
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
RTC_SetPrescaler(32767);
RTC_WaitForLastTask();
RTC_SetCounter(0);
沙发
香水城| | 2014-7-25 17:33 | 只看该作者
百度了一下有人说如下处理,果然有效,可是不知道原因,还望了解真相的告知一二!
RTC_WaitForLastTask();
RTC_SetCounter(counter);        // 设置RTC计数器
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RTC_WaitForLastTask();


那么你本来是怎么做的就不行了?

使用特权

评论回复
板凳
mmuuss586| | 2014-7-25 18:51 | 只看该作者
关闭RTC时钟看看;
设置好后,再重新打开看看;

使用特权

评论回复
地板
airwill| | 2014-7-26 07:06 | 只看该作者
手册上有介绍:

若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中的RSF位(寄存器同步标志)被硬件置1。
16.3.4  配置RTC寄存器
必须设置RTC_CRL寄存器中的CNF位,使RTC进入配置模式后,才能写入RTC_PRL、RTC_CNT、RTC_ALR寄存器。
另外,对RTC任何寄存器的写操作,都必须在前一次写操作结束后进行。可以通过查询RTC_CR寄存器中的RTOFF状态位,判断RTC寄存器是否处于更新中。仅当RTOFF状态位是’1’时,才可以写入RTC寄存器。
配置过程:
1.  查询RTOFF位,直到RTOFF的值变为’1’
2.  置CNF值为1,进入配置模式
3.  对一个或多个RTC寄存器进行写操作
4.  清除CNF标志位,退出配置模式
5.  查询RTOFF,直至RTOFF位变为’1’以确认写操作已经完成。
仅当CNF标志位被清除时,写操作才能进行,这个过程至少需要3个RTCCLK周期。

使用特权

评论回复
5
pofu007|  楼主 | 2014-7-26 10:12 | 只看该作者
香水城 发表于 2014-7-25 17:33
百度了一下有人说如下处理,果然有效,可是不知道原因,还望了解真相的告知一二!
RTC_WaitForLastTask();
...

本来是这样的,应该是标准的RTC寄存器更改流程吧。
RTC_WaitForLastTask();
RTC_SetCounter(counter);        // 设置RTC计数器
RTC_WaitForLastTask();
这样的话在第二次查询RTC_WaitForLastTask()时进入死循环。
在加入下面2个语句后就正常了。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);

使用特权

评论回复
6
pofu007|  楼主 | 2014-7-26 10:22 | 只看该作者
airwill 发表于 2014-7-26 07:06
手册上有介绍:

若在读取RTC寄存器时,RTC的APB1接口曾经处于禁止状态,则软件首先必须等待RTC_CRL寄存器中 ...

我想我知道原因了。学别人的做法,我在BKP寄存器中放置了一个字节指示标志,用来判断RTC模块是否已初始化,这样实际只有在电源中断后(我的测试版没有专门的后背的电源接口,都接在VCC上了),BKP中的指示标志丢失了,才会对RTC做完全的初始化,否者初始化的时候指示同步一下,继续原来的计数。所以,下载新的代码并复位后实际上PWR和BKP,并没有被使能,导致更改CNT寄存器失败的。
所以在加入下面2句后就正常了。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
PWR_BackupAccessCmd(ENABLE);

使用特权

评论回复
7
pofu007|  楼主 | 2014-7-26 10:31 | 只看该作者
额,现在怎么没有结贴的按钮了!~

使用特权

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

本版积分规则

6

主题

60

帖子

1

粉丝