- void RTC_LSI_Config(void)
- {
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
- /* unLock RTC write protection */
- PMU_EnableBackupAccess();
- RCM_EnableLSI();
- while(RCM_ReadStatusFlag(RCM_FLAG_LSIRDY) == RESET);
- RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
- RCM_EnableRTCCLK();
- /* Wait for RTC clock source synchro */
- RTC_WaitForSynchro();
- RTC_WaitForLastTask();
- RTC_ConfigPrescaler(50000);
- RTC_WaitForLastTask();
- /* Configure counter 0 */
- RTC_ConfigCounter(0);
- RTC_WaitForLastTask();
- /* Enable RTC alarm interrupt */
- RTC_EnableInterrupt(RTC_INT_SEC);
- RTC_WaitForLastTask();
- NVIC_EnableIRQRequest(RTC_IRQn, 0, 0);
- }
- /* RTC核心配置:LSE时钟源+1Hz计时+秒中断 */
- void RTC_LSE_Config(void)
- {
- // 1. 使能PMU时钟,访问RTC必须先开这个
- RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
- // 2. 解锁备份域,不然没法改RTC寄存器
- PMU_EnableBackupAccess();
- // 3. 开启LSE晶振,等它稳定
- RCM_ConfigLSE(RCM_LSE_OPEN);
- while(RCM_ReadStatusFlag(RCM_FLAG_LSERDY) == RESET); // 没焊晶振会卡在这
- // 选择LSE作为RTC时钟源,然后使能RTC时钟
- RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
- RCM_EnableRTCCLK();
- // 4. 等RTC时钟同步,不然配置会失效
- RTC_WaitForSynchro();
- RTC_WaitForLastTask();
- // 5. 配置预分频器,
- RTC_ConfigPrescaler(32768);
- RTC_WaitForLastTask();
- // 6. 计数器初始值设为0,从0秒开始计时
- RTC_ConfigCounter(0);
- RTC_WaitForLastTask();
- // 7. 使能秒中断,每秒触发一次
- RTC_EnableInterrupt(RTC_INT_SEC);
- RTC_WaitForLastTask();
- // 8. 配置NVIC,开启RTC中断
- NVIC_EnableIRQRequest(RTC_IRQn, 0, 0);
- }
- /* RTC中断服务函数 */
- void RTC_Isr(void)
- {
- if(RTC_ReadIntFlag(RTC_INT_SEC)) // 检查是不是秒中断
- {
- uint32_t time, h, m, s;
- time = RTC_ReadCounter(); // 读取当前计数值(单位:秒)
- // 把总秒数转成时分秒
- h = (time / 3600) % 24;
- m = (time / 60) % 60;
- s = time % 60;
- // 串口打印时间,补零看起来更整齐
- printf("%02ldh:%02ldm:%02lds\r\n", h, m, s);
- BOARD_LED_Toggle(LED2); // LED每秒翻转一次
- RTC_ClearIntFlag(RTC_INT_SEC); // 一定要清标志位,不然会一直进中断
- }
- }
三、测试效果
编译下载后,打开串口助手(波特率 115200,8N1),能看到串口每秒打印一次时间,从 00h:00m:00s 开始递增,开发板上的 计时很准,基本没偏差,比用 LSI 的时候强太多了。