STM32-RTC配置
官方对RTC的简介
如果焊接了LSE(外部低速振荡器),如上图所述,可以配置RTC使用LSE,此时尽管CPU掉电,RTC的数据仍可以恢复,即保存到后备区域(BKP),等待系统复位或者从待机模式恢复的时候,将后备区域的数据读取出来。
由于蓝桥杯嵌入式开发板CT117E没有焊接LSE晶振,所以不能使用LSE当作RTC的时钟源,而采用LSI,LSI为是40Mhz,要产生RTC需要的1Hz时钟,所以需要经过4000分频。
我们在配置的时候可以直接参考STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\RTC\Calendar以及\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\RTC\LSI_Calib两个工程。
下面是配置代码:
#include "rtc.h"
uint32_t Tmp_HH = 8, Tmp_MM = 30, Tmp_SS = 59;
void RTC_NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the RTC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
void RTC_Configuration(void)
{
// RTC_NVIC_Configuration();
/* Enable PWR and BKP clocks */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
/* Reset Backup Domain */
BKP_DeInit();
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC registers synchronization */
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Enable the RTC Second */
RTC_ITConfig(RTC_IT_SEC, DISABLE);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Set RTC prescaler: set RTC period to 1sec */
RTC_SetPrescaler(40000);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* To output second signal on Tamper pin, the tamper functionality
must be disabled (by default this functionality is disabled) */
BKP_TamperPinCmd(DISABLE);
/* Enable the RTC Second Output on Tamper Pin */
BKP_RTCOutputConfig(BKP_RTCOutputSource_None);
}
void Time_Adjust(void)
{
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
/* Change the current time */
RTC_SetCounter(Tmp_HH*3600 + Tmp_MM*60 + Tmp_SS);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
void Time_Get(void)
{
uint32_t TimeVar = RTC_GetCounter();
/* Reset RTC Counter when Time is 23:59:59 */
if (TimeVar == 0x0001517F)
{
RTC_SetCounter(0x0);
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
}
/* Compute hours */
Tmp_HH = TimeVar / 3600;
/* Compute minutes */
Tmp_MM = (TimeVar % 3600) / 60;
/* Compute seconds */
Tmp_SS = (TimeVar % 3600) % 60;
}
在官方的程序上面做出了一些小的修改:
- 由于我们没有用到RTC的秒中断,所以我们在程序中可以不用配置中断,不使能RTC的秒中断。
- 由于我们没有用到Tamper Pin(PC.13),所以不使能它。再解释一下Temper Pin是什么,Temper Pin是PC.13的复用功能,可以用来输出RTCCLK,即输出1Hz的方波。
在main函数中,需要调用RTC_Configuration()对RTC进行初始化,调用Time_Adjust()来配置RTC计数器的值,这个时候相当于时钟真正开始走动起来了,但我们要读取当前的时间的时候,调用Time_Get(),更新当前时间。