RTC实时时钟
RTC(Real Time Clock)实时时钟
- 独立定时器,可为系统提供时钟和日历。
- 和时钟配置系统在后备区,复位不清零,断电后可借助VBAT供电。
- 32位计数器:对应UNIX时间戳的秒计数器。
- 20位分频器:适应不同输入时钟。
RTC结构
RTC_CNT:计数器(32位)
RTCCLK:系统时钟输入(HSE/LSE/LEI三种时钟源)
RTC_DIV:预分频器(20位)
TR_CLK:分频后的时钟,可产生一个中断(秒中断)
RTC_CR:中断输出选择
RTC_Alarm \ WKP_STDBY:唤醒模块
背景为灰色的部分:可由VBAT供电
RTC的时钟源:
- HSE时钟128分频后。
- LSE时钟(32.768KHz)可产生一秒时钟。
- LSI时钟(40KHz)。
可产生的中断:
- RTC_Second:秒中断,及每次TR_CLK时钟(可达1秒)。
- RTC_Overflow:溢出中断,RTC_CNT溢出并回转为0时。
- RTC_Alarm:闹钟中断,RTC_CNT与RTC_CLR相等时。
初始化流程
- 开启RCC时钟:PWR和BKP
- 使能对BKP和RTC的访问:PWR_BackupAccessCmd(ENABLE)
- 开启LES时钟:RCC_LESConfig(RCC_LES_ON)//参数可选择时钟源
- 使能RTC时钟:RCC_RTCCLKCmd(ENABLE)
- 等待LSE时钟开启:while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);
- 读取RTC寄存器时,需先等待RTC_CRL寄存器的RSF位被硬件置1(寄存器同步)
- 对RTC_CLK寄存器的任何写操作,都必须在前一次写操作结束后,RTC_CR寄存器的RTOFF位为1时才能写入
- 配置RTC时钟源:RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
- 使能RTC时钟:RCC_RTCCLKCmd(ENABLE);
- 设置分频器:RTC_SetPrescaler(32768-1);//并等待
- 设置初始时间:RTC_SetCounter(1672588795);//并等待
标准库函数使用模板
RTC初始化
void RTC_init() {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP, ENABLE);
PWR_BackupAccessCmd(ENABLE);
RCC_LESConfig(RCC_LES_ON);//开启LES时钟
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) != SET);
//上面也可使用内部时钟
//RCC_LSICmd(ENABLE);
//while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) != SET);
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//RCC_RTCCLKSource_LSI
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();//等待时钟同步
RTC_WaitForLastTask();//等待写操作
RTC_SetPrescaler(32768-1);//分频(LSI时为40000-1)
RTC_WaitForLastTask();//等待写操作
RTC_SetCounter(1672588795);//设置初始时间
RTC_WaitForLastTask();//等待写操作
}
RTC_GetCounter();//返回CNT的值
RTC_GetDivider();//返回余数寄存器,0~32767代表1秒
//可借助BKP的特性,实现时间不重置
RTC配置函数
// 进入RTC配置模式
void RTC_EnterConfigMode(void);
// 退出RTC配置模式
void RTC_ExitConfigMode(void);
// 配置RTC_CNT寄存器的值
void RTC_SetCounter(uint32_t CounterValue);
// 配置RTC_DIV寄存器的值
void RTC_SetPrescaler(uint32_t PrescalerValue);
// 配置RTC_ALR寄存器的值
void RTC_SetAlarm(uint32_t AlarmValue);
标志位/事件函数
// 检查标志位/事件
FlagStatus RTC_GetFlagStatus(uint16_t RTC_FLAG);
// 清除事件或标志位
void RTC_ClearFlag(uint16_t RTC_FLAG);
// 等待写操作结束
void RTC_WaitForLastTask(void);
// 等待RTC与APB时钟同步
void RTC_WaitForSynchro(void);
读取寄存器
// 获取RTC_CNT寄存器的值
uint32_t RTC_GetCounter(void);
// 获取RTC_DIV预分频器的值
uint32_t RTC_GetDivider(void);
RTC中断函数
void RTC_ITConfig(uint16_t RTC_IT, FunctionalState NewState);
ITStatus RTC_GetITStatus(uint16_t RTC_IT);
void RTC_ClearITPendingBit(uint16_t RTC_IT);
流程图
读取RTC寄存器时,需先等待RTC_CRL寄存器的RSF位被硬件置1
对RTC_CLK寄存器的任何写操作,都必须在前一次写操作结束后,RTC_CR寄存器的RTOFF位为1时才能写入
+----+
+------------+ +--+ Second | |
| ESE/128 | | | 预分频器 +------------------------>| |
|外部高速时钟 +---->| | +----------+ | +----------+ | |
+------------+ | | RTCCLK | DIV | | | CNT | Overflow |中断|
+------------+ | +-------->|余数寄存器 +---+--->|32位计数器 +--------->| | +----+
| LSE | | | +----+-----+ +----+-----+ |输出+---->|NVIC|
|外部低速时钟 +---->| | | 计 | Alarm | | +----+
+------------+ | | | 数 +--------------->|控制|
+------------+ | | +----+-----+ 器 | | |
| LSI | | | | PRL | +----+-----+ | |
|内部低速时钟 +---->| | |重装寄存器 | | ALR | | |
+------------+ +--+ +----------+ |32位闹钟值 | +----+
+----------+
------ BY Flier
2023.9.8
Reference:江协科技、《stm32f10x用户手册》、《stm32库开发实战指南教程》