目录
1. 目标
通过HAL库控制RTC
2. 背景知识
RTC实时时钟提供了一个可编程的日历,给电就工作并且独立于所有低功耗模式以及复位模式,主要用于周期性唤醒
并且支持闰年,甚至夏令时。通过第二时钟源和数字校准电路还能进一步提高精度
3. 内容
3.1 时钟日历
在CubeMX里面将Clock Source和Calendar打开就行了
时间日期可以在CubeMX里面设置,也可以通过代码设置。(不是很懂这里设置时间的意义)
设置时间和获取时间的代码差不多,数字格式有二进制和BCD码两种可以选择。需要注意的是,获取日期必须在获取时间之后进行
稍微提一下,二进制就是变量正常储存的那种形式,BCD码就是把数字每位都用二进制表示,eg. 17(0001 0111)
RTC_DateTypeDef date = {};
HAL_RTC_SetDate(&hrtc, &date, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
RTC_TimeTypeDef time = {};
HAL_RTC_SetTime(&hrtc, &time, RTC_FORMAT_BIN);
HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
文章资源中的代码提供了一种简单的方法,以通过串口进行时间同步
3.2 时钟输出
Calibration字段可以设置输出时钟,512Hz / 1Hz
设置之后就能在GPIO界面看到了,这里是PB2
3.3 闹钟
RTC具有闹钟A和闹钟B,两个一样的,这里就只说闹钟A好了
这是CubeMX里的设置界面,大概分成两块,一块是时间设置一块是掩码设置,假如对应掩模是真,则忽略对应时间
比如这里设置的是0:1:15的闹钟,假如把分钟的掩码打开,在0点每分钟的第15s都会触发
简单写了下中断函数,注意闹钟中断既不需要在主函数中开启,也不需要在中断函数中重新打开,CubeMX里面打开中断就算配置完成了
void HAL_RTC_AlarmAEventCallback (RTC_HandleTypeDef *_hrtc) {
if (_hrtc == &hrtc) {
printf("from A IT\r\n");
}
}
3.4 时间戳
一个奇奇怪怪的功能,既可以由硬件触发也可以由软件触发
GPIO口就这样了,不可更改,不过可以选择是上升沿触发还是下降沿触发
但中断是和RTC时钟的防篡改中断一起使能的
简单的写个回调,这里是硬件触发,每按下一次按钮,生成一个时间戳
void HAL_RTCEx_TamperTimeStampIRQHandler (RTC_HandleTypeDef *_hrtc) {
if (_hrtc == &hrtc) {
RTC_TimeTypeDef stampTime;
RTC_DateTypeDef stampDate;
HAL_RTCEx_GetTimeStamp(&hrtc, &stampTime, &stampDate, RTC_FORMAT_BIN);
printf("Time Stamp (%d)\r\n", stampTime.Seconds);
}
}
3.5 备份寄存器
一共有32个寄存器,从RTC_BKP_DR0到RTC_BKP_DR31,每个能存放32位
这是一个简单的示例代码,从寄存器中读取并写入
uint32_t rtcBackup = 240630, read;
read = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);
printf("%lu\r\n", read);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, rtcBackup);
3.6 周期性唤醒
现在还没学到低功耗模式,就大概说一下,这是由一个16位向下定时器控制的功能
时钟源支持两种:RTCCLK和1Hz,如果选择RTCCLK的话,支持2 4 8 16的分频系数,这里图上的LSE低速外部时钟频率标错了应该是KHz,时间比较短在122us-32s间;1Hz的话,频率显然就是1Hz,但在这个模式下可以将16位的定时器拓展到17位,加持下可以计时1s-36h
3.7 入侵检测
大概这样,三个主要功能都没用过,就把简介摆在这里好了
3.8 问题
由于知识水平受限和时间受限等一系列原因,还是有一些问题没解决
比如理论上RTC在复位模式依然能够计时,但很显然不是太行,在参考其他一些文章后,应该是HAL库初始化RTC时,写入了新值。由于没对文章中的代码进行验证,故不提供参考链接
个人还是喜欢初始化时进行时间同步(串口,GPS,无线模块等)
附录
时钟日历
闹钟
时间戳
备份寄存器