STM32HAL学习笔记七-RTC时钟
? 本次实验工程是在第二次实验串口通信的基础上修改的。参考博客
1.RTC简介
? 实时时钟是一个独立的定时器。RTC模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。RTC模块和时钟配置系统(RCC_BDCR寄存器)处于后备区域,即在系统复位或从待机模式唤醒后,RTC的设置和时间维持不变。系统复位后,对后备寄存器和RTC的访问被禁止,这是为了防止对后备区域(BKP)的意外写操作。执行以下操作将使能对后备寄存器和RTC的访问:
-
设置寄存器RCC_APB1ENR的PWREN和BKPEN位,使能电源和后备接口时钟 -
设置寄存器PWR_CR的DBP位,使能对后备寄存器和RTC的访问。 其供电部分如图所示,当VDD断点之后,需要VBAT管脚为其供电,才能保证RTC的正常工作。
2.Cubemx配置
2.1配置低速时钟
2.2使能时钟源和日期
2.3设置初始时间
2.4更改时钟源
3.程序编写
3.1定义获取日期和时间的结构体
RTC_DateTypeDef GetData;
RTC_TimeTypeDef GetTime;
3.2主程序
HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
printf("%02d/%02d/%02d\r\n",2000 + GetData.Year, GetData.Month, GetData.Date);
printf("%02d:%02d:%02d\r\n",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
printf("\r\n");
HAL_Delay(1000);
3.3调试结果
4.优化
? 由于单片机每一次复位或上电都会调用RTC初始化的函数,而因为HAL库设置了一个BKP寄存器保存一个标志,每次单片机启动时都读取这个标志并判断是不是预先设定的值:如度果不是就初始化RTC并设置时间,再设置标志为预期值;如果是预期值就跳过初始化和时间设置,继续执行后面的程序,所以每次上电或者复位都会重置时间,于是需要优化。
可以在MX_RTC_Init()函数增加如下函数
RTC_DateTypeDef datebuff;
__HAL_RCC_BKP_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!= 0x5051)
{
__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);
datebuff = DateToUpdate;
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x5051);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)datebuff.Year);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)datebuff.Month);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)datebuff.Date);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)datebuff.WeekDay);
}
else
{
datebuff.Year = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
datebuff.Month = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);
datebuff.Date = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);
datebuff.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);
DateToUpdate = datebuff;
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
{
Error_Handler();
}
__HAL_RTC_SECOND_ENABLE_IT(&hrtc,RTC_IT_SEC);
}
|