实时时钟的特征和原理
RTCCLK:时钟来源
RTC的时钟有哪些来源呢?
如图,有3个渠道
来自于外部的LSE也就是外部的晶振来自于HSE的128分频来自于LSI
一般情况下我们都是采用外部晶振来提供时钟的,因为它还是很精确的。
BKP备份寄存器
RTC相关寄存器
具体设置可查看datasheet。
配置RTC寄存器
读RTC寄存器
RTC相关库函数
RTC一般配置步骤
源码
建议使用pc端浏览源码
rtc.h
#ifndef __RTC_H
#define __RTC_H
//时间结构体
typedef struct
{
vu8 hour;
vu8 min;
vu8 sec;
//公历日月年周
vu16 w_year;
vu8 w_month;
vu8 w_date;
vu8 week;
}_calendar_obj;
extern _calendar_obj calendar;//日历结构体
extern u8 const mon_table[12];//月份日期数据表
void Disp_Time(u8 x,u8 y,u8 size);//在制定位置开始显示时间
void Disp_Week(u8 x,u8 y,u8 size,u8 lang);//在指定位置显示星期
u8 RTC_Init(void); //初始化RTC,返回0,失败;1,成功;
u8 Is_Leap_Year(u16 year);//平年,闰年判断
u8 RTC_Alarm_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);
u8 RTC_Get(void); //更新时间
u8 RTC_Get_Week(u16 year,u8 month,u8 day);
u8 RTC_Set(u16 syear,u8 smon,u8 sday,u8 hour,u8 min,u8 sec);//设置时间
#endif
rtc.c
#include "delay.h"
#include "usart.h"
#include "rtc.h"
_calendar_obj calendar;//时钟结构体
static void RTC_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;//RTC全局中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//先占优先级1位,从优先级3位
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//先占优先级0位,从优先级4位
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//使能该通道中断
NVIC_Init(&NVIC_InitStructure);//根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
}
//实时时钟配置
//初始化RTC时钟,同时检测时钟是否工作正常
//BKP->DR1用于保存是否第一次配置的设置
//返回0:正常
//其他:错误代码
u8 RTC_Init(void)
{
//检查是不是第一次配置时钟
u8 temp=0;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);//使能PWR和BKP外设时钟
PWR_BackupAccessCmd(ENABLE);//使能后备寄存器访问
if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050)//从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
{
BKP_DeInit();//复位备份区域
RCC_LSEConfig(RCC_LSE_ON);//设置外部低速晶振(LSE),使用外设低速晶振
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET&&temp<250)//检查指定的RCC标志位设置与否,等待低速晶振就绪
{
temp++;
delay_ms(10);
}
if(temp>=250)return 1;//初始化时钟失败,晶振有问题
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);//设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
RCC_RTCCLKCmd(ENABLE);//使能RTC时钟
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_WaitForSynchro();//等待RTC寄存器同步
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_EnterConfigMode();/// 允许配置
RTC_SetPrescaler(32767); //设置RTC预分频的值
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
RTC_Set(,1,14,17,42,55); //设置时间
RTC_ExitConfigMode(); //退出配置模式
BKP_WriteBackupRegister(BKP_DR1, 0X5050);//向指定的后备寄存器中写入用户程序数据
}
else//系统继续计时
{
RTC_WaitForSynchro();//等待最近一次对RTC寄存器的写操作完成
RTC_ITConfig(RTC_IT_SEC, ENABLE);//使能RTC秒中断
RTC_WaitForLastTask();//等待最近一次对RTC寄存器的写操作完成
}
RTC_NVIC_Config();//RCT中断分组设置
RTC_Get();//更新时间
return 0; //ok
}
//RTC时钟中断
//每秒触发一次
//extern u16 tcnt;
void RTC_IRQHandler(void)
{
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)//秒钟中断
{
RTC_Get();//更新时间
}
if(RTC_GetITStatus(RTC_IT_ALR)!= RESET)//闹钟中断
{
RTC_ClearITPendingBit(RTC_IT_ALR);//清闹钟中断
RTC_Get();//更新时间
printf("Alarm Time:%d-%d-%d %d:%d:%d