[应用相关]

STM32 RTC介绍

[复制链接]
1796|25
手机看帖
扫描二维码
随时随地手机跟帖
junpeng324|  楼主 | 2018-5-28 21:54 | 显示全部楼层 |阅读模式
STM32  内部 RTC  时钟 简介
要讲到 STM32 的内部 RTC 时钟,我们首先要了解一些 STM32 的备份寄存器,备份
寄存器是 42 个 16 位的寄存器,可用来存储 84 个字节的用户应用程序数据。他们处在备
份域里,当 VDD 电源被切断,他们仍然由 VBAT 维持供电。当系统在待机模式下被唤醒,
或系统复位或电源复位时,他们也不会被复位。而 STM32 的内部 RTC 时钟就在备份寄存
器中。所以我们得到一个结论,就是要操作 RTC 时钟就要操作备份寄存器。

junpeng324|  楼主 | 2018-5-28 22:02 | 显示全部楼层
RTC 的结构框图:
1.png

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:03 | 显示全部楼层
从框图中我们可以看出,其实 RTC 时钟里面存储时钟信号的只是一个 32 位的寄存
器,如果按秒来计算的话可以存储可以记录 4294967296 秒,约合 136 年左右,作为一般
应用,这已经是足够了的。但是从这里看出我们要具体知道现在的时间是哪年哪月哪日,还
有时分秒,那么就要自己进行处理了,将读取出来的计数值,转换为我们熟悉的年月日时分
秒。接下来我们来看一下怎么操作 RTC 时钟。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:03 | 显示全部楼层
备份寄存器是 42 个 16 位的寄存器,可用来存储 84 个字节的用户应用程序数据。他们
处在备份域里,当 VDD 电源被切断,他们仍然由 VBAT 维持供电。当系统在待机模式下被
唤醒,或系统复位或电源复位时,他们也不会被复位。

使用特权

评论回复
zhangmangui| | 2018-5-28 22:07 | 显示全部楼层
学习一下   L0系列好像没看到有VBAT这个引脚啊  

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:13 | 显示全部楼层
此外,BKP 控制寄存器用来管理侵入检测和 RTC 校准功能。 复位后,对备份寄存器和
RTC 的访问被禁止,并且备份域被保护以防止可能存在的意外的写操作。执行以下操作可以
使能对备份寄存器和 RTC 的访问。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:13 | 显示全部楼层
1.通过设置寄存器 RCC_APB1ENR 的 PWREN 和 BKPEN 位来打开电源和后备接口的时

2. 电源控制寄存器(PWR_CR)的 DBP 位来使能对后备寄存器和 RTC 的访问。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:14 | 显示全部楼层
  打开相应的时钟
从上面我们知道,如果我们操作 RTC,那么我们就要操作备份寄存器,所以呢我
们要打开一个是备份区域时钟。而一般操作 RTC 的话还会用到一个时钟, 就是
电源时钟, 在电源控制里面有操作 RTC 的一些设置,所以我们还有将电源控制
的时钟打开。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:14 | 显示全部楼层
代码为:
/* 使能 PWR 电源时钟和 BKP 备份区域外设时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//打开电源时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//打开存储器时钟

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:15 | 显示全部楼层
使能备份寄存器操作
可以使用 PWR_BackupAccessCmd()函数(从开头的 PWR 我们就知道这个设置是
在电源控制部分设置的,所以我们要打开电源控制的时钟) 。它只有一个参数,也就
是设置的状态,我们要使能所以设为: ENABLE。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:17 | 显示全部楼层
  复位备份寄存器
当然这个操作不要每次都执行,因为备份区域的复位将导致之前存在的数据丢失,
所以要不要复位,要看情况而定。我们可以使用 BKP_DeInit()函数。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:18 | 显示全部楼层
  设置外部低速时钟
我们要使用外部的低速时钟来控制 RTC,代码为:
RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振。
在开启外部低速时钟的时候,我们还要确定它是否成功起振,之后才能够接着操作,所
以我们还要检测,外部低速时钟是否开启。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:19 | 显示全部楼层
代码为:
/* 检查指定的 RCC 标志位设置与否,等待低速晶振(LSE)就绪 */
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
等待它起振好了之后将它作为 RTC 的时钟,代码为:
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置 RTC 时钟(RTCCLK),选择 LSE 作
为 RTC 时钟

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:22 | 显示全部楼层
  使能 RTC  时钟
打开 RTC 时钟,代码为:
RCC_RTCCLKCmd(ENABLE); //使能 RTC 时钟
在对 RTC 操作的时候,注意连续操作的时候还要检测它是否执行完成,才能够接着对
起进行操作,所以操作完之后再检测是否操作完成。代码为:
RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完成

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:24 | 显示全部楼层
等待 RTC  时钟寄存器同步
代码为: RTC_WaitForSynchro(); //等待 RTC 寄存器同步

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:25 | 显示全部楼层
开启秒中断
我们要读取时钟秒更新一次,所以我们开启秒中断。代码为
RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能 RTC 秒中断
然后等待操作完成。 RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:35 | 显示全部楼层
然后设置 RTC  时钟的预分频
我们要进行 32767 分频。所以代码为: RTC_SetPrescaler(32767); //设置 RTC 预分频
的值
然后等待操作完成: RTC_WaitForLastTask(); //等待最近一次对 RTC 寄存器的写操作完

使用特权

评论回复
junpeng324|  楼主 | 2018-5-28 22:40 | 显示全部楼层
设置初始化时间
也就是要初始化的时钟存入到 32 位寄存器,这里原理就是,我们直接将对应的时间数
据转换为 16 进制数写入到 32 位寄存器中,每当这个 32 位寄存器加 1,那么比 0 时 0
分 0 秒,多了一秒就是 0 时 0 分 1 秒。因此到时候我们直接读取寄存器值即可。

使用特权

评论回复
tomyoct| | 2018-5-29 09:13 | 显示全部楼层
支持下,但是这个RTC确实没有DS1302等方便的,自动计算时间。

使用特权

评论回复
junpeng324|  楼主 | 2018-5-29 09:41 | 显示全部楼层
void rtc_init()
{
NVIC_InitTypeDef NVIC_InitStructure; //中断结构体定义
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);//打开电源时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP,ENABLE);//打开存储器时钟
PWR_BackupAccessCmd(ENABLE);//使能或者失能 RTC 和后备寄存器访问
BKP_DeInit();//将外设 BKP 的全部寄存器重设为缺省值
RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE)
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY)==RESET);//检查指定的 RCC 标志位设置
与否
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//设置 RTC 时钟(RTCCLK)
RCC_RTCCLKCmd(ENABLE);//使能或者失能 RTC 时钟
RTC_WaitForSynchro(); //等待 RTC 寄存器同步
RTC_WaitForLastTask();//等待最近一次对 RTC 寄存器的写操作完成
RTC_ITConfig(RTC_IT_SEC,ENABLE);//使能或者失能指定的 RTC 中断
RTC_WaitForLastTask();//等待最近一次对 RTC 寄存器的写操作完成
RTC_SetPrescaler(32767);//设置预分频 使用外部晶振为 32.768K,要想 1s 中断则预
分频数设置为 32767,系统会在此数字基础上加 1
RTC_WaitForLastTask();//等待最近一次对 RTC 寄存器的写操作完成
/* 设置 NVIC 参数 */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //打开 RTC 的全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //抢占优先级为 0
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //响应优先级为 1
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能
NVIC_Init(&NVIC_InitStructure);
}

使用特权

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

本版积分规则

37

主题

1130

帖子

8

粉丝