STM32F103 RTC实时时钟详解

简介

RTC本质是一个定时器,有后备区域,该区域用来保证持续计时,需要单独供电。当复位或唤醒后,后备区域有写保护,所以需要修改后备区域时即修改时间时,需要先取消后备区域BKP的写保护。
RTC核心有两个模块,20位的预分频器与32位的可编程计数器。
RTC可以产生三种中断,
一般设置预分频器产生1秒的时间基准TR_CLK,通过RTC_CR寄存器设置,可以每秒产生一次秒中断
计数器有一个RTC_ALR闹钟寄存器,通过设置RTC_CR寄存器,当RTC_CNT与RTC_ALR的值匹配时,发生一次闹钟中断
当RTC_CNT溢出时,会产生溢出中断


由于RTC可以单独运行,而我们通过软件访问RTC的计数器是通过APB1总线接口,如果APB1上电后直接访问RTC的寄存器,而此时RTC内部寄存器还没有更新,那么读取的数据往往是0,所以需要等到RTC_CRL寄存器的RFS位(寄存器同步标志位,bit3)被硬件置1后,再读取。   

RTC配置步骤 

1.使能电源时钟,并使能 RTC RTC 后备寄存器写访问。

首先要使能RTC电源时钟与RTC后备区域时钟,同时关闭写保护

__HAL_RCC_PWR_CLK_ENABLE(); /* 使能电源时钟 PWR */
__HAL_RCC_BKP_CLK_ENABLE(); /* 使能备份时钟 */
HAL_PWR_EnableBkUpAccess(); /* 取消备份区域写保护 */

 2.初始化 RTC,设置 RTC 的分频,以及配置 RTC 参数。

RTC_HandleTypeDef g_rtc_handle; /* RTC控制句柄 */
g_rtc_handle.Instance = RTC;
g_rtc_handle.Init.AsynchPrediv = 32767; /*时钟周期设置,理论值:32767, 这里也可以用 RTC_AUTO_1_SECOND */
g_rtc_handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
HAL_RTC_Init(&g_rtc_handle);

__HAL_RTC_ALARM_ENABLE_IT(&g_rtc_handle, RTC_IT_SEC);   /* 允许秒中断 */
    
HAL_NVIC_SetPriority(RTC_IRQn, 0x2, 0);                 /* 优先级设置 */
HAL_NVIC_EnableIRQ(RTC_IRQn);                           /* 使能RTC中断通道 */

3.开启外部低速振荡器LSE,选择 RTC 时钟,并使能。

调用 HAL_RCC_OscConfig 函数配置开启 LSE
调用 HAL_RCCEx_PeriphCLKConfig 函数选择 RTC 时钟源。
使能 RTC 时钟函数为__HAL_RCC_RTC_ENABLE
RCC_OscInitTypeDef rcc_oscinitstruct = {0};
RCC_PeriphCLKInitTypeDef rcc_periphclkinitstruct = {0};

__HAL_RCC_RTC_ENABLE(); /* RTC时钟使能 */
    
/* 使用寄存器的方式去检测LSE是否可以正常工作 */
RCC->BDCR |= 1 << 0;    /* 开启外部低速振荡器LSE */
while (retry && ((RCC->BDCR & 0X02) == 0))  /* 等待LSE准备好 */
{
	delay_ms(5);
}

rcc_oscinitstruct.OscillatorType = RCC_OSCILLATORTYPE_LSE ; /* 选择要配置的振荡器 */
rcc_oscinitstruct.LSEState = RCC_LSE_ON;                    /* LSE状态:开启 */
rcc_oscinitstruct.PLL.PLLState = RCC_PLL_NONE;              /* PLL不配置 */
HAL_RCC_OscConfig(&rcc_oscinitstruct);                      /* 配置设置的rcc_oscinitstruct */
        
rcc_periphclkinitstruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;   /* 选择要配置外设 RTC */
rcc_periphclkinitstruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;   /* RTC时钟源选择LSE */
HAL_RCCEx_PeriphCLKConfig(&rcc_periphclkinitstruct);                /* 配置设置的rcc_periphclkinitstruct */

HAL_PWR_EnableBkUpAccess(); /* 取消备份区写保护 */
HAL_RTCEx_BKUPWrite(&g_rtc_handle, 0+ 1, 0x5050);

时间设置

RTC第一次上电初始化时间流程:

由于第一次未对RTC初始化设置BKP寄存器时,   BKP寄存器0的值非0x5050 且0x5051,往往此时对RTC进行第一次时间设置。

uint16_t bkpflag = HAL_RTCEx_BKUPRead(&g_rtc_handle, 0 + 1);

if ((bkpflag != 0X5050) && (bkpflag != 0x5051))         /* 之前未初始化过,重新配置 */
{
    rtc_set_time(2025, 5, 19, 11, 43, 00);              /* 设置时间 */
}

 后续复位上电等,时间都会默认设置为这个时间。

更改时钟步骤如下:

__HAL_RCC_PWR_CLK_ENABLE(); /* 使能电源时钟 */
__HAL_RCC_BKP_CLK_ENABLE(); /* 使能备份域时钟 */
HAL_PWR_EnableBkUpAccess(); /* 取消备份域写保护 */
RTC->CRL |= 1 << 4;         /* 允许配置 */

/* 更改时间,修改RTC_CNT寄存器 
 * RTC->CNTL
 * RTC->CNTH
*/

RTC->CRL &= ~(1 << 4);      /* 配置更新 */
while (!__HAL_RTC_ALARM_GET_FLAG(&g_rtc_handle, RTC_FLAG_RTOFF));       /* 等待RTC寄存器操作完成, 即等待RTOFF == 1 */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值