转自: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();
如果有不正确的地方也请各位多多指教,本人及时纠正;欢迎大家来和我相互交流学习,谢谢大家。