初学stm32 --- RTC实时时钟
目录
RTC简介
常用的RTC方案
STM32 F1 RTC框图介绍
后备寄存器和RTC寄存器特性(F1)
F1 RTC相关寄存器介绍
RCC_APB1ENR寄存器编辑
PWR_CR寄存器
RCC_BDCR寄存器
RTC_CRL寄存器
RTC_CRH寄存器
RTC_PRLH寄存器
RTC_PRLL寄存器
RTC_CNTH寄存器
RTC_CNTL寄存器
RTC相关的HAL库驱动介绍
RTC基本驱动步骤(F1)
时间设置和读取
RTC简介
实时时钟(Real Time Clock,RTC),本质是一个计数器,计数频率常为秒,专门用来记录时间。
普通定时器无法掉电运行,所以不能拿来作时钟。
RTC特性:
1,能提供时间(秒钟数)
2,能在MCU掉电后运行
3,低功耗
常用的RTC方案
1,一般都需要设计RTC外围电路;
2,一般都可以给RTC设置独立的电源;
3,多数RTC的寄存器采用BCD码存储时间信息;
STM32 F1 RTC框图介绍
1,RTC预分频器 2,32位可编程计数器
3,待机唤醒 4,RTC控制寄存器与APB1接口
3个时钟源(HSE / 128)、 (LSI 40kHz)(LSE 32.768kHz)
后备寄存器和RTC寄存器特性(F1)
1、部分寄存器写保护
RTC_PRL、RTC_ALR、RTC_CNT和RTC_DIV寄存器不会被系统复位
2、数据存储功能
RTC和后备寄存器不会被系统或电源复位源复位;当从待机模式唤醒时,也不会被复位。 后备寄存器可用于保存掉电时的数据。
3、独立工作
RTC和后备寄存器通过一个开关供电,在VDD有效时该开关选择VDD供电,否则由VBAT引脚供电。在VBAT供电时仍可继续工作。
4、2个独立复位
APB1接口由系统复位;RTC核心只能由后备域复位;
F1 RTC相关寄存器介绍
RTC基本配置步骤
1、使能对RTC的访问 RCC_APB1ENR PWR_CR
使能PWR && BKP时钟、使能对后备寄存器和RTC的访问权限
2、设置RTC时钟源 RCC_BDCR
激活LSE,设置RTC的计数时钟源为LSE
3、进入配置模式 RTC_CRL
等待 RTOFF位为1,设置CNF位为1
4、设置RTC寄存器 RTC_PRL RTC_CNT
设置分频值、计数值等,一般先只设置分频值,CNT的设置独立
5、退出配置模式 清除CNF位,等待RTOFF 为1即配置完成
RCC_APB1ENR寄存器
PWR_CR寄存器
RCC_BDCR寄存器
RTC_CRL寄存器
RTC_CRH寄存器
RTC_PRLH寄存器
RTC_PRLL寄存器
RTC_CNTH寄存器
注意:进入配置模式才能对寄存器进行操作
RTC_CNTL寄存器
注意:进入配置模式才能对寄存器进行操作
RTC相关的HAL库驱动介绍
RTC基本驱动步骤(F1)
1、使能电源时钟并使能后备域访问
__HAL_RCC_PWR_CLK_ENABLE 使能电源时钟
__HAL_RCC_BKP_CLK_ENABLE 使能备份时钟
HAL_PWR_EnableBkUpAccess 使能备份访问
2、开启LSE/选择RTC时钟源/使能RTC时钟
HAL_RCC_OscConfig 开启LSE
HAL_RCCEx_PeriphCLKConfig 选择RTC时钟源
__HAL_RCC_RTC_ENABLE 使能RTC时钟
3、初始化RTC,设置分频值以及工作参数
HAL_RTC_Init 初始化RTC
HAL_RTC_MspInit 完成RTC底层初始化工作
4、设置RTC的日期和时间
操作寄存器方式实现rtc_set_time
5、获取RTC当前日期和时间
定义rtc_get_time函数
时间设置和读取
由于F1的RTC没有日历寄存器,使用时只存储总秒数,不利于直接设置和显示,所以我们还需要编写函数把时间变成我们日常的日历时间
可以开启秒中断,来更新时间。
__HAL_RTC_ALARM_ENABLE_IT(&g_rtc_handle, RTC_IT_SEC); /* 允许秒中断 */
可以通过设置RTC闹钟(RTC_ALR)来设置闹钟。当可编程计数器的值与RTC_ALR中的32位值相等时,即触发一个闹钟事件,并且产生RTC闹钟中断。
/**
* @brief 设置闹钟, 具体到年月日时分秒
* @note 以1970年1月1日为基准, 往后累加时间
* 合法年份范围为: 1970 ~ 2105年
* @param syear : 年份
* @param smon : 月份
* @param sday : 日期
* @param hour : 小时
* @param min : 分钟
* @param sec : 秒钟
* @retval 0, 成功; 1, 失败;
*/
uint8_t rtc_set_alarm(uint16_t syear, uint8_t smon, uint8_t sday, uint8_t hour, uint8_t min, uint8_t sec)
{
uint32_t seccount = 0;
seccount = rtc_date2sec(syear, smon, sday, hour, min, sec); /* 将年月日时分秒转换成总秒钟数 */
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能电源时钟 */
__HAL_RCC_BKP_CLK_ENABLE(); /* 使能备份域时钟 */
HAL_PWR_EnableBkUpAccess(); /* 取消备份域写保护 */
/* 上面三步是必须的! */
RTC->CRL |= 1 << 4; /* 允许配置 */
RTC->ALRL = seccount & 0xffff;
RTC->ALRH = seccount >> 16;
RTC->CRL &= ~(1 << 4); /* 配置更新 */
while (!__HAL_RTC_ALARM_GET_FLAG(&g_rtc_handle, RTC_FLAG_RTOFF)); /* 等待RTC寄存器操作完成, 即等待RTOFF == 1 */
return 0;
}
需要注意的是:在每次设置闹钟和,设置时间的时候都需要取消写保护,即完成以下三步:
__HAL_RCC_PWR_CLK_ENABLE(); /* 使能电源时钟 */
__HAL_RCC_BKP_CLK_ENABLE(); /* 使能备份域时钟 */
HAL_PWR_EnableBkUpAccess(); /* 取消备份域写保护 */
/* 上面三步是必须的! */