转自:http://www.amobbs.com/thread-5523800-1-1.html

本人也是STM32初学者,也买了野火M3实验板学习,学到STM32-RTC时感觉RTC涉及的体系比较杂乱,所以做了相应的笔记,现分享给和我一样的初学者们,也当为大家提供点小力吧!大神们就勿喷了。


STM32 的RTC 时钟配置 因为涉及了许多的寄存器,如:BKP、PWR、RTC ,弄得很杂乱,现在由我来做个RTC配置的总结。
RTC简介:RTC是一个实时时钟是一个独立的定时器,RTC模块拥有一组连续计数的计数器,在相应软件配置下,可以提供时钟、日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
配置RTC前需知:

BKP:
RTC模块和时钟配置系统的寄存器是在后备区域的(即BKP),通过BKP后备区域来存储RTC配置的数据可以让在系统复位或待机模式下唤醒后 RTC里面配置的数据维持不变。

PWR:
PWR为电源的寄存器,我们需要用到的是电源控制寄存器(PWR_CR),通过使能PWR_CR的DBP位来取消后备区域BKP的写保护。

RTC :
由一组可编程计数器组成,分成两个主要模块。第一个模块是RTC的预分频
模块,它可编程产生最长为1 秒的RTC时间基准TR_CLK 。RTC的预分频模块包含了一个20位的
可编程分频器(RTC 预分频器) 。如果在RTC_CR寄存器中设置了相应的允许位,则在每个实时时钟(RTC)TR_CLK 周期中RTC产生一个中断( 秒中断) 。第二个模块是一个32位的可编程计数器,可被初始
化为当前的系统时间。系统时间按TR_CLK 周期累加并与存储在RTC_ALR寄存器中的可编程时间相比较,如果RTC_CR控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。 



需知部分告一段落,如果想更详细的了解可以打开你的stm32使用手册查看。

下面讲解下配置整体过程:

第一步: 通过设置寄存器RCC_APB1ENR的PWREN 和BKPEN位来打开电源和后备接口的时钟 
调用库函数:
RCC_APB1PeriphClockCmd (RCC_APB1Periph_PWR | RCC_APB1Periph_BKP,ENABLE );

第二步:电源控制寄存器(PWR_CR) 的DBP位来使能对后备寄存器和RTC的访问
调用库函数:
PWR_BackupAccessCmd(ENABLE ); 


第三步:初始化复位BKP寄存器

调用库函数:

BKP_DeInit ();

第四步:设置RTCCLK,如下图:



我们需要将RTCCLK 设置为 LSE OSC  这个32.768KHZ的晶振。

调用的库函数:

RCC_LSEConfig (RCC_LSE_ON);

While(!RCC_GetFlagStatus (RCC_FLAG_HSERDY));//设置后需要等待启动

第五步:将RTC输入时钟 选择为LSE时钟 输入并使能RTC,等待RTC和APB时钟同步

调用库函数:

RCC_RTCCLKConfig (RCC_RTCCLKSource_LSE);//选择LSE为RTC设备 的 时钟
RCC_RTCCLKCmd (ENABLE );//使能RTC
RTC_WaitForSynchro();//等待同步

第六步:配置RTC 时钟 参数。

1.   查询RTOFF位,直到RTOFF的值变为’1’ 
2.   置CNF值为1 ,进入配置模式 
3.   对一个或多个RTC寄存器进行写操作 
4.   清除CNF标志位,退出配置模式 
5.   查询RTOFF,直至RTOFF位变为’1’ 以确认写操作已经完成。 
仅当CNF标志位被清除时,写操作才能进行,这个过程至少需要3个RTCCLK 周期。

好!就按照上述步骤 用 库函数来配置:

/* 1.   查询RTOFF位,直到RTOFF的值变为1 */
RTC_WaitForLastTask();//大家可以打开函数库看看这个函数内部的代码,就是查询RTOFF的值

/*
  2.   置CNF值为1 ,进入配置模式 
  3.   对一个或多个RTC寄存器进行写操作
  4.   清除CNF标志位,退出配置模式 
*/
RTC_SetPrescaler(32767);   // 这里配置了预分频值,大家可以打开函数库看看这个函数的内部的代码,里面就有包含了2、3、4讲述的操作。
  补充:根据以下公式,这些位用来定义计数器的时钟频率: 
    fTR_CLK = fRTCCLK/(PRL[19:0]+1) ,我们LSE是32.768KHZ = 32768Hz,由上述公式就可以知道最终f TR_CLK = 1Hz  那么刚刚刚好就是1秒
  
记住了每完成一个操作 一般都要查询RTOFF来判断是否RTC正在更新数据,如果是则等待他完成!!!

TC_WaitForLastTask();//等待更新结束


RTC_ITConfig(RTC_IT_SEC, ENABLE);//配置秒中断

RTC_WaitForLastTask();//等待更新结束


好了,整个RTC的配置 也就是按照这个步骤配置下来,大家好好理解下吧,多多打开你的STM32使用手册 和 STM32官方库说明书,看多几遍几个寄存器几个函数内部代码更有助于理解!

整体配置RTC代码:

void RTC_Configuration(void)
{
        /* Enable PWR and BKP clocks */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
        
        /* Allow access to BKP Domain */
        PWR_BackupAccessCmd(ENABLE);
        
        /* Reset Backup Domain */
        BKP_DeInit();
        
        /* Enable LSE */
        RCC_LSEConfig(RCC_LSE_ON);

        /* Wait till LSE is ready */
        while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
        {}
        
        /* Select LSE as RTC Clock Source */
        RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
        
        /* Enable RTC Clock */
        RCC_RTCCLKCmd(ENABLE);
        
        /* Wait for RTC registers synchronization */
        RTC_WaitForSynchro();
        
        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();
        
        /* Set RTC prescaler: set RTC period to 1sec */
        RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)*/
  
  
        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();
        

        /* Enable the RTC Second */
        RTC_ITConfig(RTC_IT_SEC, ENABLE);

        /* Wait until last write operation on RTC registers has finished */
        RTC_WaitForLastTask();

如果有不正确的地方也请各位多多指教,本人及时纠正;欢迎大家来和我相互交流学习,谢谢大家。

posted on 2014-10-08 19:38  CT1104  阅读(1285)  评论(0编辑  收藏  举报