RTC_First_Config:这个函数负责首次配置RTC,包括启用PWR和BKP外设时钟,解除后备域写保护,启用和配置外部32.768kHz晶振,配置RTC预分频器以生成1Hz时钟。如果需要,还可以启用秒中断。
void RTC_First_Config(void) {
// 启用PWR和BKP外设时钟(来自APB1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
// 解除对后备域的写保护
PWR_BackupAccessCmd(ENABLE);
// 重置后备寄存器模块/备份寄存器模块复位
BKP_DeInit();
// 启用外部32.768KHZ晶振
RCC_LSEConfig(RCC_LSE_ON);
// 等待LSE稳定
while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
// 配置RTC时钟源为LSE(外部低速晶振32.768KHZ)
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
// 启用RTC时钟
RCC_RTCCLKCmd(ENABLE);
// 等待APB1时钟与RTC时钟同步,这样才能读写寄存器
RTC_WaitForSynchro();
// 在写入寄存器前,必须确保前一个操作已完成
RTC_WaitForLastTask();
// 设置RTC预分频器,使RTC时钟为1Hz
RTC_SetPrescaler(32767); // RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1)
// 等待寄存器写入完成
RTC_WaitForLastTask();
// 如果不使用RTC秒中断,可以忽略以下两行
// RTC_ITConfig(RTC_IT_SEC, ENABLE); // 启用秒中断
// RTC_WaitForLastTask(); // 等待写入完成
}
RTC_Config:这个函数检查后备寄存器的数据,如果数据丢失(即表示这是第一次配置或者后备电池掉电后重启),它会调用RTC_First_Config
重新配置RTC,并向后备寄存器写入一个特殊标记以指示RTC已配置。如果后备寄存器的数据没有丢失(即RTC已配置),它会简单地启用RTC时钟并等待时钟同步。
void RTC_Config(void) {
// 在后备寄存器1中存储了一个特殊字符0xA5A5
// 第一次上电或后备电池掉电后,该寄存器数据丢失,表示RTC数据丢失,需要重新配置
if (BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5) { // 判断寄存器数据是否丢失
RTC_First_Config(); // 重新配置RTC
BKP_WriteBackupRegister(BKP_DR1, 0xA5A5); // 配置完成后,向后备寄存器写入特殊字符0xA5A5
} else {
// 如果后备寄存器没有掉电,则无需重新配置RTC
// 这里我们可以利用RCC_GetFlagStatus()函数查看本次复位类型
if (RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET) {
// 这是上电复位
} else if (RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET) {
// 这是外部RST引脚复位
}
// 清除RCC中的复位标志
RCC_ClearFlag();
// 虽然RTC模块无需重新配置,并且掉电后在后备电池供电下继续运行
// 但是每次上电后,仍需要启用RTCCLK
RCC_RTCCLKCmd(ENABLE); // 启用RTCCLK
RTC_WaitForSynchro(); // 等待RTC时钟与APB1时钟同步
// 如果不使用RTC秒中断,可以忽略以下两行
// RTC_ITConfig(RTC_IT_SEC, ENABLE); // 启用秒中断
// RTC_WaitForLastTask(); // 等待操作完成
}
}
逻辑总结
- 启用必要的外设时钟:PWR和BKP时钟。
- 解除后备域的写保护:允许访问和配置后备域。
- 重置后备寄存器:确保寄存器处于初始状态。
- 配置LSE并等待其稳定:设置LSE作为RTC的时钟源。
- 配置RTC时钟源并启用RTC:确保RTC使用正确的时钟源。
- 等待时钟同步:确保RTC与系统时钟同步。
- 设置预分频器:使RTC计时精确到秒。
- 检查并初始化RTC:根据备份寄存器的状态决定是否初次配置RTC。
- (可选)启用RTC中断:根据需要启用中断功能。