目录
背景
RTC(实时时钟)和后备寄存器
32.768HZ 如何产生1S定时
RTC配置程序
第一次上电RTC配置
第1步、启用备用寄存器外设时钟和PWR外设时钟
第2步、使能RTC和备份寄存器访问
第3步、备份寄存器初始化
第4步、开启LSE
第5步、等待LSE启动后稳定状态
第6步、配置LSE为RTC时钟源
第7步、使能RTC时钟
第8步、设置RTC预分频
第9步、设置秒中断
第10步、秒中断函数封装
背景
通过本篇文章对常用的RTC时钟(实时时钟)进行说明. 以及了解如何通过程序来区分上电复位和管脚复位。
RTC(实时时钟)和后备寄存器
RTC晶振 (LSE:外部低速时钟):32.768KHZ
STM32单片机内部集成了一个40KHZ的RC振荡器,内部RC振荡器会会因为温度产生漂移,精度不够高,因此使用32.768HZ的LSE作为RTC的时钟源。RTC备用电池,在单片机主电源断开的时候,给RTC时钟供电,也可以用于保存备用存储器中的数据(计时器的时间值,以及用户临时存放的数据),备用寄存器 20字节保存用户数据
32.768HZ 如何产生1S定时信号
![](https://i-blog.csdnimg.cn/direct/4c6bac4cc5824890bf9aad6f68444d60.png)
RTC配置程序
第一次上电RTC配置
void RTC_First_Config(void){ //首次启用RTC的设置RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//启用PWR和BKP的时钟(from APB1)PWR_BackupAccessCmd(ENABLE);//后备域解锁BKP_DeInit();//备份寄存器模块复位RCC_LSEConfig(RCC_LSE_ON);//外部32.768KHZ晶振开启 while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);//等待稳定 RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RTC时钟源配置成LSE(外部低速晶振32.768KHZ) RCC_RTCCLKCmd(ENABLE);//RTC开启 RTC_WaitForSynchro();//开启后需要等待APB1时钟与RTC时钟同步,才能读写寄存器 RTC_WaitForLastTask();//读写寄存器前,要确定上一个操作已经结束RTC_SetPrescaler(32767);//设置RTC分频器,使RTC时钟为1Hz,RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) RTC_WaitForLastTask();//等待寄存器写入完成 //当不使用RTC秒中断,可以屏蔽下面2条
// RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断
// RTC_WaitForLastTask();//等待写入完成
}
第1步、启用备用寄存器外设时钟和PWR外设时钟
通过stm32的数据手册可以知道RTC需要是能APB1
![](https://i-blog.csdnimg.cn/direct/e17c957a83ba49dd8117f03f16bfff84.png)
![](https://i-blog.csdnimg.cn/direct/cc10a58764fc48ccb02934f399236a8a.png)
![](https://i-blog.csdnimg.cn/direct/fcb107010ee941ac9a9df85a9032eaef.png)
RCC_APB1Periph_PWR
主要用于控制电源管理单元(Power Control Unit,简称PWR)的时钟使能。
在STM32中,RCC(复位和时钟控制)模块负责管理微控制器的时钟树和外设的晶振、内部振荡器以及各种时钟源的分频和倍频。具体到RCC_APB1Periph_PWR ,它是APB1总线上的一个外设,用于控制电源管理单元(PWR)的时钟使能。通过使能或失能PWR的时钟,可以控制电源管理功能的工作状态,进而影响整个系统的功耗管理。
LSE作为RTC时钟源之后,即使VDD断电,仍然可以通过RTC纽扣电池(备用电池)使得RTC外设继续工作。因此要启用PWR外设的时钟!
RCC_APB1Periph_BKP
是和后备存储器相关
第2步、使能RTC和备份寄存器访问
后面需要对RTC进行分频设置和备份寄存器初始化!
第3步、备份寄存器初始化
第4步、开启LSE
第5步、等待LSE启动后稳定状态
第6步、配置LSE为RTC时钟源
stm32数据手册中的时钟树可以RTC的时钟源有三个
1)LSE
2) LSI(40khz)
3)HSE的128分频
第7步、使能RTC时钟
第8步、设置RTC预分频
1)等待 RTC 寄存器(RTC_CNT, RTC_ALR and RTC_PRL)与 RTC 的 APB 时钟同步
2)等待上一次rtc寄存器写操作完成
3)设置预分频
4)等待rtc寄存器写完成
固件库函数具体实现(ST公司提供)
所以要特别注意实际上的预分频数为设置值+1
第9步、设置秒中断
第10步、秒中断函数封装
void RTC_IRQHandler(void){ //RTC时钟1秒触发中断函数(名称固定不可修改)if (RTC_GetITStatus(RTC_IT_SEC) != RESET){}RTC_ClearITPendingBit(RTC_IT_SEC); RTC_WaitForLastTask();
}
RTC配置程序(用于main函数调用)
void RTC_Config(void){ //实时时钟初始化//在BKP的后备寄存器1中,存了一个特殊字符0xA5A5//第一次上电或后备电源掉电后,该寄存器数据丢失,表明RTC数据丢失,需要重新配置if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5){//判断寄存数据是否丢失 RTC_First_Config();//重新配置RTC BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);//配置完成后,向后备寄存器中写特殊字符0xA5A5}else{//若后备寄存器没有掉电,则无需重新配置RTC//这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET){//这是上电复位}else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET){//这是外部RST管脚复位} RCC_ClearFlag();//清除RCC中复位标志//虽然RTC模块不需要重新配置,且掉电后依靠后备电池依然运行//但是每次上电后,还是要使能RTCCLKRCC_RTCCLKCmd(ENABLE);//使能RTCCLK RTC_WaitForSynchro();//等待RTC时钟与APB1时钟同步//当不使用RTC秒中断,可以屏蔽下面2条
// RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能秒中断
// RTC_WaitForLastTask();//等待操作完成}}
可用的部分是前面的10个,以为备份寄存器为20个字节。
RCC_FLAG_PORRST就是上电复位、RCC_FLAG_PINRST管脚复位