目录
一、基本概念
实时时钟(RTC,Real-Time Clock)是一种专门设计用于在电子设备中提供精确时间信息的硬件组件。RTC通常被设计成一个独立的定时器,它能够持续地追踪时间,即使在主电源关闭的情况下也能继续运行,这是因为RTC通常由一个小电池(如CR2032纽扣电池)供电,确保时间的连续性。RTC模块内部有一个连续计数的计数器,这个计数器在软件配置下可以提供日历功能,包括显示秒、分、时、日、月、年和星期等信息。由于RTC使用的是BCD(Binary-Coded Decimal)编码来存储时间信息,这使得它可以方便地进行日期和时间的计算。
二、周期唤醒和闹钟
1、CubeMX配置
①RCC设置
②RTC配置
③中断配置
④设置RTC时钟源为LSE
2、代码编写
①进入主循环前,先使能周期唤醒中断
//启动周期唤醒中断
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 0, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
while (1)
{
}
②定义回调函数
#include "rtc.h"
#include "usart.h"
#include <stdio.h>
//1s 周期唤醒回调函数
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
//读取日期和读取时间函数必须成对使用,否则不能连续更新时间和日期
//因为读取时间寄存器开始,就会锁定日期寄存器
if(HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN)==HAL_OK)
{
HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BIN);
printf("%d.%d.%d %d:%d:%d \r\n",sDate.Year+2000,sDate.Month,sDate.Date,sTime.Hours,sTime.Minutes,sTime.Seconds);
}
}
//闹钟A
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
static uint16_t TiggleA=0;
TiggleA++;
printf("TiggleA:%d \r\n",TiggleA);
}
//闹钟B
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{
static uint16_t TiggleB=0;
TiggleB++;
printf("TiggleB:%d \r\n",TiggleB);
}
三、RTC备份寄存器
1、概念
RTC(Real-Time Clock)备份寄存器是在微控制器或微处理器中用于保存关键数据的特殊存储区域,即使在系统主电源断开时也能保持数据不丢失。这些寄存器通常由一个独立的电池或备用电源供电,以确保数据的持久性。
2、代码编写
①B闹钟启动时将时间数据保存到备份寄存器中
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{
static uint16_t TiggleB=0;
TiggleB++;
printf("TiggleB:%d \r\n",TiggleB);
RTC_SaveToBKUP();//保存到备份寄存器
}
②每次重新上电时加载时间数据
RTC_LoadFromBKUP();//加载备份寄存器数据
while (1)
{
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
HAL_Delay(500);
}
③bsp_rtc.c
#include "bsp_rtc.h"
#include "usart.h"
#include <stdio.h>
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
//读取日期和读取时间函数必须成对使用,否则不能连续更新时间和日期,
//因为读取时间寄存器开始,就会锁定日期寄存器
if(HAL_RTC_GetTime(hrtc, &sTime, RTC_FORMAT_BIN)==HAL_OK)
{
HAL_RTC_GetDate(hrtc, &sDate, RTC_FORMAT_BIN);
printf("%d.%d.%d %d:%d:%d \r\n",sDate.Year+2000,sDate.Month,sDate.Date,sTime.Hours,sTime.Minutes,sTime.Seconds);
}
}
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
{
static uint16_t TiggleA=0;
TiggleA++;
printf("TiggleA:%d \r\n",TiggleA);
}
void HAL_RTCEx_AlarmBEventCallback(RTC_HandleTypeDef *hrtc)
{
static uint16_t TiggleB=0;
TiggleB++;
printf("TiggleB:%d \r\n",TiggleB);
RTC_SaveToBKUP();
}
void RTC_SaveToBKUP()
{
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, sTime.Hours);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, sTime.Minutes);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, sTime.Seconds);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, sDate.Year);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, sDate.Month);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, sDate.Date);
printf("RTC_SaveToBKUP end \r\n");
}
void RTC_LoadFromBKUP()
{
sTime.Hours=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR0);
sTime.Minutes=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1);
sTime.Seconds=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR2);
HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
sDate.Year=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR3);
sDate.Month=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR4);
sDate.Date=HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR5);
HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
printf("RTC_LoadFromBKUP end \r\n");
}
四、RTC入侵检测和时间戳
1、概念
RTC入侵检测: RTC的入侵检测功能可以用来监控微控制器的某些异常情况,如电源故障、非法访问等。当检测到这样的事件时,RTC可以触发中断,甚至锁定一些关键的寄存器,防止数据被篡改。例如,在电源电压下降到某个阈值以下时,RTC可以记录这个事件发生的时间点,从而帮助诊断问题或保护数据的完整性。
RTC时间戳: RTC的时间戳功能可以用来记录特定事件发生的精确时间。这在日志记录、故障分析、安全审计等方面非常重要。例如,当系统检测到一个错误或异常,它可以记录下当前RTC的时间,这样维护人员就可以知道这个事件发生在什么具体时间,有助于后续的故障排查和系统维护。
2、软件配置
3、代码编写
void HAL_RTCEx_Tamper2EventCallback(RTC_HandleTypeDef *hrtc)
{
printf("Tamper2 is Trigger!!! \r\n");
printf("%d.%d.%d %d:%d:%d \r\n",sDate.Year+2000,sDate.Month,sDate.Date,sTime.Hours,sTime.Minutes,sTime.Seconds);
}