caizhiwei 发表于 2021-2-13 12:27

【AT-START-F407测评】04 RTC驱动

本帖最后由 caizhiwei 于 2021-2-13 12:32 编辑

   用于片内集成RTC外设,可以用起来做时钟或者日历,今天它来了!

RTC简介
实时时钟是一个独立的定时器。 RTC 模块拥有一组连续计数的计数器,在相应软件配置下,可提供时钟
日历的功能。修改计数器的值可以重新设置系统当前的时间和日期。
RTC 模块和时钟配置系统( RCC_BDC 寄存器)处于后备区域,即在系统复位或从待机模式唤醒后, RTC
的设置和时间维持不变。
系统复位后,对后备寄存器和 RTC 的访问被禁止,这是为了防止对后备区域(BRKP)的意外写操作。
执行以下操作将使能对后备寄存器和 RTC 的访问:
● 设置 寄存器RCC_APB1EN的PWREN和BKPEN位, 使能电源和后 备接口时 钟
● 设置 寄存器PWR_CTRL的DBP位, 使能对后备寄 存器和RTC的 访问。


主要特性
● 可编程的预分频系数:分频系数最高为2^20。
● 32位的可编程计数器,可用于较长时间段的测量。
● 2个分离的时钟:用于APB1接口的PCLK1和RTC时钟( RTC时钟的频率必须小于PCLK1时
钟频率的四分之一以上)。
● 可以选择以下三种RTC的时钟源:
 HSE时钟除以128
 LSE振荡器时钟
 LSI振荡器时钟( 详见3.2.8节RTC时钟)
● 2个独立的复位类型:
 APB1接口由系统复位;
 RTC核心(预分频器、闹钟、计数器和分频器)只能由后备域复位(详见 3.1.3节)。
● 3个专门的可屏蔽中断:
 闹钟中断,用来产生一个软件可编程的闹钟中断。
 秒中断,用来产生一个可编程的周期性中断信号(最长可达 1秒)。
 溢出中断,指示内部可编程计数器溢出并回转为0的状态。


1. 初始化RTC,这里需要注意的是:通过读备份域寄存器来判断是否需要写入时间初始值,如果RTC电池没有断电,则跳过此。

初始化函数如下:

/**
* @briefRTC Init.
* @paramNone
* @retval None
*/
void BSP_RTC_Init(void)
{
      /* Enable PWR and BKP clocks */
      RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR | RCC_APB1PERIPH_BKP, ENABLE);

      /* Allow access to BKP Domain */
      PWR_BackupAccessCtrl(ENABLE);

      /* Check Backup data registers is correct*/
      if (BKP_ReadBackupReg(BKP_DT1) != 0x5051)
      {
                /* Reset Backup Domain */
                BKP_Reset();      
                /* Enable the LSI OSC */
                RCC_LSEConfig(RCC_LSE_ENABLE);
                /* Wait till LSI is ready */
                while(RCC_GetFlagStatus(RCC_FLAG_LSESTBL) == RESET);
                /* Select the RTC Clock Source */
                RCC_RTCCLKConfig(RCC_RTCCLKSelection_LSE);
               
                /* 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();
               
                /* Set RTC prescaler: set RTC period to 1sec */
                RTC_SetDIV(32767);
                /* Wait until last write operation on RTC registers has finished */
                RTC_WaitForLastTask();
               
                /* Set the RTC time */
                BSP_RTC_Set(2020, 8, 8, 8, 8, 0);
                /* Wait until last write operation on RTC registers has finished */
                RTC_WaitForLastTask();
               
                /* Writes data to Backup Register */
                BKP_WriteBackupReg(BKP_DT1, 0x5051);
      }
      else
      {
                /* Wait for RTC registers synchronization */
                RTC_WaitForSynchro();
                /* Wait until last write operation on RTC registers has finished */
                RTC_WaitForLastTask();
                /* Clear RTC pending flag */
                RTC_ClearFlag(RTC_FLAG_PACE);
                /* Wait until last write operation on RTC registers has finished */
                RTC_WaitForLastTask();
      }
}                                                   
2. 通过不断查询的方式,就可以获取时间了!

void BSP_RTC_Time_Printf(void)
{
      if(RTC_GetFlagStatus(RTC_FLAG_PACE) != RESET)      
      {
                /* Update current time */
                BSP_RTC_Get();
               
                /* print the current time */
                printf("\r\n");
                printf("%d/%d/%d ", calendar.w_year, calendar.w_month, calendar.w_date);
                printf("%02d:%02d:%02d %s", calendar.hour, calendar.min, calendar.sec, weekday_table);
      
                /* Clear the RTC Second flag */
                RTC_ClearFlag(RTC_FLAG_PACE);
               
                /* Wait until last write operation on RTC registers has finished */
                RTC_WaitForLastTask();
      }
}

最后效果图如下:


代码附件:



页: [1]
查看完整版本: 【AT-START-F407测评】04 RTC驱动