简介
RTC (Real Time Clock):实时时钟
- STM32 的 RTC 外设,实质是一个掉电后还继续运行的定时器。RTC是个独立的BCD定时器/计数器。提供一个日历时钟,两个可编程闹钟中断,以及一个具有中断功能的周期性可编程唤醒标志。RTC还包含用于管理低功耗模式的自动唤醒单元。
- 两个32位寄存器包含二进码十进制格式(BCD)的秒,分钟,小时(12或24小时制),星期几,日期,月份和年份。此外,还可以提供二进制的亚秒值。系统可以自动将月份的天数补偿为28,29(闰年),30,31天。并且还可以进行夏令时补偿。
主要特性
void RCC_RTCCLKConfig(uint32_t CLKSource);//时钟源选择
void RCC_RTCCLKCmd(FunctionalState NewState)//时钟使能
ErrorStatus RTC_Init(RTC_InitTypeDef* RTC_InitStruct);
typedef struct
{
uint32_t RTC_HourFormat; //小时格式:24/12
uint32_t RTC_AsynchPrediv; //异步分频 系数
uint32_t RTC_SynchPrediv; //同步分频系数
}RTC_InitTypeDef
//设置时间
ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
//获取时间
void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
//设置日期
ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
//获取日期
void RTC_GetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct);
//获取到亚秒的信息
uint32_t RTC_GetSubSecond(void);
//禁止或使能RTC闹钟。
ErrorStatus RTC_AlarmCmd(uint32_t RTC_Alarm, FunctionalState NewState);
//RTC闹钟时间配置。
void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
//获取RTC闹钟的时间配置
void RTC_GetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
//功能配置RTC AlarmA/B的亚秒
void RTC_AlarmSubSecondConfig(uint32_t RTC_Alarm, uint32_t RTC_AlarmSubSecondValue, uint32_t RTC_AlarmSubSecondMask);
//得到RTC的亚秒时间。
uint32_t RTC_GetAlarmSubSecond(uint32_t RTC_Alarm);
//配置RTC唤醒时钟源
void RTC_WakeUpClockConfig(uint32_t RTC_WakeUpClock);
//配置RTC唤醒计数
void RTC_SetWakeUpCounter(uint32_t RTC_WakeUpCounter);
//得到唤醒定时器的计数值
uint32_t RTC_GetWakeUpCounter(void);
//关闭WAKE UP
RTC_WakeUpCmd(DISABLE);
//使能或禁止RTC中断
void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState);
//查询RTC标志,主要用于非中断函数
FlagStatus RTC_GetFlagStatus(uint32_t RTC_FLAG);
//清除RTC标志,主要用于非中断函数
void RTC_ClearFlag(uint32_t RTC_FLAG);
//查询RTC中断标志
ITStatus RTC_GetITStatus(uint32_t RTC_IT);
//清除RTC中断标志
void RTC_ClearITPendingBit(uint32_t RTC_IT);
//取消写保护
void RTC_WriteProtectionCmd(FunctionalState NewState);
//进入配置模式,RTC_ISR_INITF位设置为1
ErrorStatus RTC_EnterInitMode(void);
//退出初始化模式。
void RTC_ExitInitMode(void)
//从备份数据寄存器读出数据。
uint32_t RTC_ReadBackupRegister(uint32_t RTC_BKP_DR);
//写数据到RTC备份数据寄存器
void RTC_WriteBackupRegister(uint32_t RTC_BKP_DR, uint32_t Data);
//使能或禁止RTC中断
void RTC_ITConfig(uint32_t RTC_IT, FunctionalState NewState);
- 使能PWR时钟:RCC_APB1PeriphClockCmd();
- 使能后备寄存器访问: PWR_BackupAccessCmd();
- 配置RTC时钟源,使能RTC时钟:
RCC_RTCCLKConfig();
RCC_RTCCLKCmd();
如果使用LSE,要打开LSE:RCC_LSEConfig(RCC_LSE_ON);- 初始化RTC(同步/异步分频系数和时钟格式):RTC_Init ();
- 设置时间:RTC_SetTime ();
- 设置日期:RTC_SetDate();
#define RTC_BKP_VALE 0x2021
void Rtc_Init(void)
{
RTC_InitTypeDef RTC_InitStruct;
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
//1、使能PWR时钟:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR,ENABLE);
//2、使能后备寄存器访问: 这类寄存器是掉电保存数据的
PWR_BackupAccessCmd(ENABLE);
if(RTC_ReadBackupRegister(RTC_BKP_DR0) != RTC_BKP_VALE)
{
//3、配置RTC时钟源,使能RTC时钟:
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
RCC_RTCCLKCmd(ENABLE);
//要打开LSE:
RCC_LSEConfig(RCC_LSE_ON);
delay_ms(50); //延时等待时钟稳定
RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24; //时间格式
RTC_InitStruct.RTC_AsynchPrediv = 0x7F; //异步分频器
RTC_InitStruct.RTC_SynchPrediv = 0xFF; //同步分频器
//4、 初始化RTC(同步/异步分频系数和时钟格式):
RTC_Init(&RTC_InitStruct);
RTC_TimeStruct.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
RTC_TimeStruct.RTC_Hours = 16; //时
RTC_TimeStruct.RTC_Minutes = 36; //分
RTC_TimeStruct.RTC_Seconds = 00; //秒
//5、 设置时间:
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
RTC_DateStruct.RTC_Year = 20; //20年,前年20要自己补
RTC_DateStruct.RTC_Month = 8; //月
RTC_DateStruct.RTC_Date = 19; //日
RTC_DateStruct.RTC_WeekDay = 3; //星期
//6、设置日期:
RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
//写后备寄存器
RTC_WriteBackupRegister(RTC_BKP_DR0, RTC_BKP_VALE);
}
}
所有 RTC 中断均与 EXTI 控制器相连。要使能 RTC 闹钟中断,需按照以下顺序操作:
将 EXTI 线 17 配置为中断模式并将其使能,然后选择上升沿有效。
配置 NVIC 中的 RTC_Alarm IRQ 通道并将其使能。
配置 RTC 以生成 RTC 闹钟(闹钟 A 或闹钟 B)。
①:RTC已经初始化好相关参数。
②:关闭闹钟:RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
③:配置闹钟参数:RTC_SetAlarm();3
④:开启闹钟:RTC_AlarmCmd(RTC_Alarm_A,EABLE);
⑤:开启配置闹钟中断:
RTC_ITConfig();
EXTI_Init();
NVIC_Init();⑥:编写中断服务函数:RTC_Alarm_IRQHandler();
//闹钟A
void RTC_Alarm_AInit(void)
{
RTC_TimeTypeDef RTC_AlarmTime;
RTC_AlarmTypeDef RTC_AlarmStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//2、关闭闹钟:
RTC_AlarmCmd(RTC_Alarm_A,DISABLE);
//闹钟时间设置
RTC_AlarmTime.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
RTC_AlarmTime.RTC_Hours = 16; //时
RTC_AlarmTime.RTC_Minutes = 36; //分
RTC_AlarmTime.RTC_Seconds = 30; //秒
RTC_AlarmStruct.RTC_AlarmTime = RTC_AlarmTime; //时间设置
RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; //无掩码位 按实际时间来响应闹钟
RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay; //按星期来闹钟
RTC_AlarmStruct.RTC_AlarmDateWeekDay = RTC_Weekday_Wednesday; //星期3
//3、配置闹钟参数:
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStruct);
//4、开启闹钟:
RTC_AlarmCmd(RTC_Alarm_A,ENABLE);
//5、开启配置闹钟中断:
RTC_ITConfig(RTC_IT_ALRA,ENABLE);
EXTI_InitStruct.EXTI_Line = EXTI_Line17; //中断线17
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStruct.EXTI_LineCmd= ENABLE; //中断线使能
//初始化线上中断,设置触发条件等。
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn; //NVIC通道,在stm32f4xx.h可查看通道 (可变)
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
//配置中断分组(NVIC),并使能中断。
NVIC_Init(&NVIC_InitStruct);
}
void RTC_Alarm_IRQHandler(void)
{
//判断中断标志是否为1
if(EXTI_GetITStatus(EXTI_Line17) == SET)
{
//判断是否为闹钟A
if(RTC_GetFlagStatus(RTC_FLAG_ALRAF) == SET)
{
//闹钟响应事件
PFout(9) = 0;
RTC_ClearFlag(RTC_FLAG_ALRAF);
}
//清空标志位
EXTI_ClearITPendingBit(EXTI_Line17);
}
}
//闹钟B
void RTC_Alarm_BInit(void)
{
RTC_TimeTypeDef RTC_AlarmTime;
RTC_AlarmTypeDef RTC_AlarmStruct;
EXTI_InitTypeDef EXTI_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//2、关闭闹钟:
RTC_AlarmCmd(RTC_Alarm_B,DISABLE);
//闹钟时间设置
RTC_AlarmTime.RTC_H12 = RTC_H12_PM; //对于24小时格式,这个参数可以不用
RTC_AlarmTime.RTC_Hours = 16; //时
RTC_AlarmTime.RTC_Minutes = 36; //分
RTC_AlarmTime.RTC_Seconds = 35; //秒
RTC_AlarmStruct.RTC_AlarmTime = RTC_AlarmTime; //时间设置
RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_None; //无掩码位 按实际时间来响应闹钟
RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date; //按日期来闹钟
RTC_AlarmStruct.RTC_AlarmDateWeekDay = 19; //19日
//3、配置闹钟参数:
RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_B, &RTC_AlarmStruct);
//4、开启闹钟:
RTC_AlarmCmd(RTC_Alarm_B,ENABLE);
//5、开启配置闹钟中断:
RTC_ITConfig(RTC_IT_ALRB,ENABLE);
EXTI_InitStruct.EXTI_Line = EXTI_Line17; //中断线17
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; //中断模式
EXTI_InitStruct.EXTI_Trigger= EXTI_Trigger_Rising; //上升沿触发
EXTI_InitStruct.EXTI_LineCmd= ENABLE; //中断线使能
//初始化线上中断,设置触发条件等。
EXTI_Init(&EXTI_InitStruct);
NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn; //NVIC通道,在stm32f4xx.h可查看通道 (可变)
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x01; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x01; //响应优先级
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //使能
//配置中断分组(NVIC),并使能中断。
NVIC_Init(&NVIC_InitStruct);
}
main.c
int main(void)
{
RTC_TimeTypeDef RTC_TimeStruct;
RTC_DateTypeDef RTC_DateStruct;
//NVIC分组(一个工程当中只能配置一次分组)抢占优先级2位,值范围:0~3;响应优先级2位,值范围:0~3;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
Delay_Init();
Led_Init();
Usart1_Init();
Rtc_Init();
RTC_Alarm_AInit();
while(1)
{
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
printf("时间:%d:%d:%d\r\n", RTC_TimeStruct.RTC_Hours, RTC_TimeStruct.RTC_Minutes,
RTC_TimeStruct.RTC_Seconds);
printf("日期:20%d年%d月%d日,星期%d\r\n\r\n",RTC_DateStruct.RTC_Year,
RTC_DateStruct.RTC_Month, RTC_DateStruct.RTC_Date, RTC_DateStruct.RTC_WeekDay);
delay_s(1);
}
return 0;
}
- RTC已经初始化好相关参数。
- 关闭WakeUp:RTC_WakeUpCmd(DISABLE);
- 配置WakeUp时钟分频系数/来源: RTC_WakeUpClockConfig();
- 设置WakeUp自动装载寄存器:RTC_SetWakeUpCounter();
- 使能WakeUp : RTC_WakeUpCmd( ENABLE);
- 开启配置闹钟中断:
RTC_ITConfig();
EXTI_Init();
NVIC_Init();- 编写中断服务函数: RTC_WKUP_IRQHandler();
ErrorStatus RTC_SetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct);
函数功能:时间设置
uint32_t RTC_Format:存储格式
RTC_Format_BIN:二进制存储
RTC_Format_BCD:BCD码格式
typedef struct
{
uint8_t RTC_Hours; //时
uint8_t RTC_Minutes; //分
uint8_t RTC_Seconds; //秒
uint8_t RTC_H12; //上下午
}RTC_TimeTypeDef;
↩︎
ErrorStatus RTC_SetDate(uint32_t RTC_Format, RTC_DateTypeDef* RTC_DateStruct)
函数功能:日期设置
uint32_t RTC_Format:存储格式
RTC_Format_BIN:二进制存储
typedef struct
{
uint8_t RTC_WeekDay; //星期
uint8_t RTC_Month; //月
uint8_t RTC_Date; //日
uint8_t RTC_Year; //年
}RTC_DateTypeDef;
↩︎
void RTC_SetAlarm(uint32_t RTC_Format, uint32_t RTC_Alarm, RTC_AlarmTypeDef* RTC_AlarmStruct);
函数功能:设置闹钟
uint32_t RTC_Format:存储格式
RTC_Format_BIN:二进制存储
RTC_Format_BCD:BCD码格式
uint32_t RTC_Alarm:选择哪个闹钟
typedef struct
{
RTC_TimeTypeDef RTC_AlarmTime; //时间设置结构体
uint32_t RTC_AlarmMask; //掩码位
uint32_t RTC_AlarmDateWeekDaySel; //选择闹钟响应方式(日期,星期)
uint8_t RTC_AlarmDateWeekDay; //日期或者星期的设置
} RTC_AlarmTypeDef;
typedef struct
{
uint8_t RTC_Hours; //时
uint8_t RTC_Minutes; //分
uint8_t RTC_Seconds; //秒
uint8_t RTC_H12; //上下午
}RTC_TimeTypeDef;
https://blog.csdn.net/wprpr/article/details/108183825?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2.control