目录

RTC的初始化与基本使用

RTC的初始化

RTC的基本使用

参考文献


RTC的初始化与基本使用

STM32 的实时时钟(RTC)是一个独立的定时器。STM32 的 RTC 模块拥有一组连续计数 的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当 前的时间和日期。

RTC 模块和时钟配置系统(RCC_BDCR 寄存器)是在后备区域,即在系统复位或从待机模式 唤醒后 RTC 的设置和时间维持不变。但是在系统复位后,会自动禁止访问后备寄存器和 RTC, 以防止对后备区域(BKP)的意外写操作。所以在要设置时间之前, 先要取消备份区域(BKP) 写保护

RTC 的简化框图:

RTC 由两个主要部分组成(参见图 18.1.1),第一部分(APB1 接口)用来和 APB1 总线相连。 此单元还包含一组 16 位寄存器,可通过 APB1 总线对其进行读写操作。APB1 接口由 APB1 总 线时钟驱动,用来与 APB1 总线连接。

另一部分(RTC 核心)由一组可编程计数器组成,分成两个主要模块。第一个模块是 RTC 的 预分频模块,它可编程产生 1 秒的 RTC 时间基准 TR_CLK。RTC 的预分频模块包含了一个 20 位的可编程分频器(RTC 预分频器)。如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个 TR_CLK 周期中 RTC 产生一个中断(秒中断)。第二个模块是一个 32 位的可编程计数器,可被 初始化为当前的系统时间,一个 32 位的时钟计数器,按秒钟计算,可以记录 4294967296 秒, 约合 136 年左右,作为一般应用,这已经是足够了的。

RTC 还有一个闹钟寄存器 RTC_ALR,用于产生闹钟。系统时间按 TR_CLK 周期累加并与存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许 位,比较匹配时将产生一个闹钟中断。

RTC 内核完全独立于 RTC APB1 接口,而软件是通过 APB1 接口访问 RTC 的预分频值、计 数器值和闹钟值的。但是相关可读寄存器只在 RTC APB1 时钟进行重新同步的 RTC 时钟的上升 沿被更新,RTC 标志也是如此。这就意味着,如果 APB1 接口刚刚被开启之后,在第一次的内 部寄存器更新之前,从 APB1 上读取的 RTC 寄存器值可能被破坏了(通常读到 0)。因此,若 在读取 RTC 寄存器曾经被禁止的 RTC APB1 接口,软件首先必须等待 RTC_CRL 寄存器的 RSF 位(寄存器同步标志位,bit3)被硬件置 1。

RTC的初始化

void RTC_Init(u8 hh,u8 mm,u8 ss)
{//中断的初始化配置NVIC_InitTypeDef NVIC_InitStructure;//中断初始化结构体RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);//RTC需要的时钟总线不是APB2下的,而是APB1//RCC_APB1Periph_BKP 备份寄存器//RCC_APB1Periph_PWR  电源NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//中断请求名称NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;//子优先级NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//配置通道是否开启(ENABLE:1为开启)NVIC_Init(&NVIC_InitStructure);//中断初始化//RTC时钟配置PWR_BackupAccessCmd(ENABLE);//PWR下的能源控制的功能函数->BKP->备份寄存器通电//                              该函数功能:给备份寄存器通电BKP_DeInit();//BKP重置(等价于默认初始化)RCC_LSICmd(ENABLE);//使能LSI内部时钟while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0);//等待LSI时钟使能完成RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//RTC时钟--利用LSI时钟频率进行计数RCC_RTCCLKCmd(ENABLE);//对RTC时钟进行使能//中断进行配置RTC_ITConfig(RTC_IT_SEC,ENABLE);//中断配置函数--RTC_IT_SEC:秒中断RTC_WaitForLastTask();//等待上一次任务完成的应答RTC_WaitForSynchro();//RTC初始化系统配置RTC_WaitForLastTask();//等待上一次任务完成的应答RTC_SetPrescaler(40000-1);//时钟分频---对应的技术周期的影响RTC_WaitForLastTask();//等待上一次任务完成的应答RTC_SetCounter(hh*3600+mm*60+ss);//初始化RTC中的计数值rtctime_value = hh*3600+mm*60+ss;//这里的变量是程序当中的全局变量(此处未列出是变量定义)RTC_WaitForLastTask();//等待上一次任务完成的应答
}

我们要访问 RTC 和备份区域就必须先使能电源时钟和备份区域时钟。设置RCC_APB1ENR寄存器的PWREN和BKPEN位来使能电源和后备接口时钟

RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR, ENABLE);

要向备份区域写入数据,就要先取消备份区域写保护(写保护在每次硬复位之后被使能), 否则是无法向备份区域写入数据的。我们需要用到向备份区域写入一个字节,来标记时钟已经 配置过了,这样避免每次复位之后重新配置时钟。取消备份区域写保护的库函数实现方法是:

PWR_BackupAccessCmd(ENABLE);

在取消备份区域写保护之后,我们可以先对这个区域复位,以清除前面的设置,当然这个 操作不要每次都执行,因为备份区域的复位将导致之前存在的数据丢失,所以要不要复位,要 看情况而定。然后我们使能外部低速振荡器,注意这里一般要先判断 RCC_BDCR 的 LSERDY 位来确定低速振荡器已经就绪了才开始下面的操作。 备份区域复位的函数是:

BKP_DeInit();//BKP重置(等价于默认初始化)

使能对应的是时钟:

根据上面的时钟可以看到,使能LSI内部时钟后,对RTCCLKRTC时钟配置对应的时钟源(由于是用LSI,所以配置时钟源为LSI),配置好RTXCCLK时钟的时钟源后对RTC时钟进行使能。

 RCC_LSICmd(ENABLE);//使能LSI内部时钟while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0);//等待LSI时钟使能完成RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);//RTC时钟--利用LSI时钟频率进行计数RCC_RTCCLKCmd(ENABLE);//对RTC时钟进行使能

RTC(Real Time Clock)是实时时钟的意思,它其实和TIM有点类似,也是利用计数的原理,选择RTC时钟源,再进行分频,到达计数的目的。

RTC的秒中断功能类似SysTick系统滴答的功能。RTC秒中断功能其实是每计数一次就中断一次。注意,秒中断并非一定是一秒的时间,它是由RTC时钟源和分频值决定的“秒”的时间,当然也是可以做到1秒钟中断一次。
————————————————
版权声明:本文为CSDN博主「蚂蚁经书」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lilp2896/article/details/98875436

这里要注意由于是编写的时间程序,所以说按照1s依次中断,故按照上图的LSI时钟源的频率40000hz,进行时间分频的时候设置40000,以达到1Hz频率的目的

读写寄存器前,要确定上一个操作已经结束:RTC_WaitForLastTask();既等待直到对RTC寄存器的最近一次写操作完成。

 //中断进行配置RTC_ITConfig(RTC_IT_SEC,ENABLE);//中断配置函数--RTC_IT_SEC:秒中断RTC_WaitForLastTask();//等待上一次任务完成的应答

等待直到RTC寄存器(RTC_CNT,RTC_ALR和RTC_PRL)与RTC APB时钟同步:

 RTC_WaitForSynchro();//RTC初始化系统配置RTC_WaitForLastTask();//等待上一次任务完成的应答

为RTC定时器设置初值(由于对RTC进行了基本的初始化后进行的操作都要经过APB1口,所以都要等待直到对RTC寄存器的最近一次写操作完成):

 RTC_SetCounter(hh*3600+mm*60+ss);//初始化RTC中的计数值rtctime_value = hh*3600+mm*60+ss;//这里的变量是程序当中的全局变量(此处未列出是变量定义)RTC_WaitForLastTask();//等待上一次任务完成的应答

RTC的基本使用

主要使用RTC_GetCounter函数和RTC_SetCounter函数

 rtctime_value=RTC_GetCounter();
    RTC_SetCounter(hh*3600+mm*60+ss);

根据需要配置中断服务函数,例如时间显示程序的中断服务函数:

extern u8 nowtime[];
void RTC_IRQHandler(void)
{u32 counter;if(RTC_GetITStatus(RTC_IT_SEC)==1)//判断执行的是否是秒中断{ //个人理解,如果有多个中断操作时,可以用此方法来使不同中断区别执行RTC_ClearITPendingBit(RTC_IT_SEC);//清除秒中断标志位,好为下次中断做准备RTC_WaitForLastTask();counter=RTC_GetCounter();RTC_WaitForLastTask();if(counter==(23*3600+59*60*59)){RTC_SetCounter(0x00);RTC_WaitForLastTask();}nowtime[0]=counter/3600%24;nowtime[1]=counter%3600/60;nowtime[2]=counter%3600%60;USART2_COMUP();//其他的串口功能}
}

参考文献

[1] RTC_WaitForSynchro() https://blog.csdn.net/qinrenzhi/article/details/82558556

[2] STM32不完全手册_库函数版本_V3.1

[3] Stm32 中RTC秒中断的使用方法及例子 https://blog.csdn.net/lilp2896/article/details/98875436

【STM32】RTC的初始化与基本使用(CT117E电路)相关推荐

  1. STM32 RTC LSE 初始化失败 卡在 RTC_ICSR_INITF 或者 LSERDY

    问题描述 在使用STM32 RTC时钟的时候,想使用外部的32.768K Hz的高精度带温度补偿的 LSE 时钟源. 但是调用MX_RTC_Init()初始化的时候都会卡住.debug进去,可以看到卡 ...

  2. STM32 RTC应用 内部唤醒中断 (Internal Wakeup)

    STM32 RTC应用 周期性中断及内部唤醒(Internal Wakeup) 1. 介绍 STM32的RTC(实时时钟)模块,提供了多种功能,当前以STM32L4系列的RTC功能最为丰富,此处基于S ...

  3. STM32 RTC时钟掉电日期不更新 STM32 HAL库RTC时钟配置

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 STM32 RTC时钟掉电日期不更新 & STM32 HAL库RTC时钟配置 一.STM32CubeMX RTC配置 二.RT ...

  4. stm32 RTC时钟配置

    stm32--RTC实时时钟 一.关于时间 2038年问题 在计算机应用上,2038年问题可能会导致某些软件在2038年无法正常工作.所有使用UNIX时间表示时间的程序都将将受其影响,因为它们以自19 ...

  5. 纠结的STM32 RTC时钟源LSE

    一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题.直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题. 这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻 ...

  6. 用stm32模拟遥控器初始化电调(电调解锁)(电调行程校准)(附百度云例程)

    用stm32模拟遥控器初始化电调(电调行程校准)(电调解锁) 亲测可用的例程 链接:https://pan.baidu.com/s/1MwcWBU15Z7YJ3Dz0mA15ew 提取码:1234 硬 ...

  7. c语言中什么叫喂狗,STM32是怎么初始化看门狗和喂狗的

    STM32是怎么初始化看门狗和喂狗的 看门狗初始化步骤: 1.IWDG_PR和IWDG_RLR寄存器具有写保护功能.要修改这两个寄存器的值,必须先向 IWDG_KR寄存器中写入0x5555. 2.设置 ...

  8. STM32 RTC时钟源LSE

    一开始,所有实验都是在神舟板上去完成,根本就没有发现RTC的问题.直到我们自己画板来后调试时,才发现STM32 RTC的外部时钟源存在问题. 这也算是STM32的一个鸡肋,对于LSE外部晶振太过于苛刻 ...

  9. 【STM32】LED初始化基础以及基本使用方法(CT117E电路)

    目录 LED的使用 LED灯的初始化 LED灯的控制(寄存器or库函数) 参考 LED的使用 LED灯的初始化 void LED_INIT(void) {// 初始化结构体GPIO_InitTypeD ...

最新文章

  1. angular2初入眼帘之-搭个环境
  2. Mac下删除废纸篓内文件
  3. 大话目标检测经典模型(RCNN、Fast RCNN、Faster RCNN)
  4. kafka 削峰_从面试角度一文学完 Kafka
  5. 自学stm32的一些个人经验
  6. Dubbo--002--例子程序
  7. poj 匈牙利二分匹配算法2239 Selecting Courses
  8. 【AI视野·今日NLP 自然语言处理论文速览 第十七期】Thu, 1 Jul 2021
  9. Clion解决c++源文件多个编译运行
  10. Github之First day on Github,带你学习并完成任务点,纯手敲超详细教程!(下)
  11. 联想电脑管家图文介绍:联想电脑管家怎么下载?
  12. App Store 审核指南(最新)
  13. Keil AC5/Keil AC6/IAR指定数据绝对存储地址
  14. ORA-16401: archivelog rejected by RFS
  15. 014基于深度学习的脑电癫痫自动检测系统-2018(300引用)
  16. 基于C#实现的在线聊天室的桌面系统软件
  17. 栅格计算器函数之Con
  18. Java开发-虚拟机安装及使用(VirtualBox、VMware)
  19. IntelliJ IDEA 性能优化
  20. 通信行业和互联网行业对比分析

热门文章

  1. 如何让字体随窗口缩放自动调整大小
  2. c语言数组下标越界检查程序,数组下标越界
  3. Android常用秘籍总结
  4. Mac 活动监视器 闪退 终极解决
  5. liunx安装ODBC
  6. 完美世界的线上测试题
  7. uni-app或者小程序爬scroll-view标签中white-space: nowrap的坑
  8. 简洁版轮式小车走直线
  9. 【IT名人堂】何云飞:阿里云数据库的架构演进之路
  10. 元宇宙房地产:又一个疯狂的加密市场吗?