STM32-RTC

RTC简介

  1. RTC是一个独立的定时器,它可以连续计数和提供了时钟日历功能。使用BKP寄存器存储具有掉电保存功能
  2. 存粹的计时的,
  3. 触发中断

    ——闹钟中断,用来产生一个可编程的闹钟中断。

    ——秒中断,用来产生一个可编程的周期性中断信号(最快1秒,最慢1秒,只能1秒)

    ——溢出中断,指示内部可编程计数器溢出并回传为0的状态。

  1. RTC的特性掉电之后保存数据,但是f1的日期数据是保存到运行寄存器的(掉电丢失)
  2. 它是一个 32 位的计数器只能向上计 数。它的时钟来源有三种,分别为高速外部时钟的 128 分频( HSE/128 )、 低速内部时钟 LSI 以及低速外部时钟 LSE。
  3. 时间寄存器,日期寄存器(32位的)分别存储时分秒,年月日。

启用RTC流程:

开始遇到的问题:

  1. 

  2. 

   3. 

   4. 

   5. 

  6.   开启串口用于打印时间信息:

STM32CubeMX设置RTC就完成了,以下是代码:

  1.  定义结构体变量,获取数据

 RTC_TimeTypeDef GET_Time; /* 获取时间结构体 */ 

 RTC_DateTypeDef GET_Date; /* 获取时期结构体 */  

  2.  打印数据
        /* 打印时间结构体数据 */
        HAL_RTC_GetDate(&hrtc, &GET_Date, RTC_FORMAT_BIN);
        HAL_RTC_GetTime(&hrtc, &GET_Time, RTC_FORMAT_BIN);
 
        /* 打印时期结构体数据 */
        printf("%04d/%02d/%02d/\r\n",2000+GET_Date.Year,GET_Date.Month,GET_Date.Date);
        printf("%02d:%02d:%02d:\r\n",GET_Time.Hours,GET_Time.Minutes,GET_Time.Seconds);        

        /* 延时 */
        HAL_Delay(1000);

 

 

打印日历成功

注意:这个是掉电丢失的!,因为f103的RTC功能日期是保存到BKP里面的,但是我门每次复位或掉电之后,都是会重复初始化 void MX_RTC_Init(void)这个函数,所以掉电之后或复位之后重新计时。

怎么掉电不丢失:

  1.  掉电丢失的问题一

   可以看到图二这里面根据CubeMX里面的配置初始化了存储时期与时间的结构体(变量)如下图一

图一

    /** Initialize RTC and set the Time and Date
    */
    sTime.Hours = 0x20;
    sTime.Minutes = 0x44;
    sTime.Seconds = 0x00;

    if( HAL_RTC_SetTime( &hrtc, &sTime, RTC_FORMAT_BCD ) != HAL_OK )
    {
        Error_Handler();
    }

    DateToUpdate.WeekDay = RTC_WEEKDAY_WEDNESDAY;
    DateToUpdate.Month = RTC_MONTH_MAY;
    DateToUpdate.Date = 0x31;
    DateToUpdate.Year = 0x23;

 

 

void MX_RTC_Init(void): 图二

  /* RTC init function */
  void MX_RTC_Init(void)
  {
  
    /* USER CODE BEGIN RTC_Init 0 */
  
    /* USER CODE END RTC_Init 0 */
  
    RTC_TimeTypeDef sTime = {0};
   RTC_DateTypeDef DateToUpdate = {0};
 
   /* USER CODE BEGIN RTC_Init 1 */
 
   /* USER CODE END RTC_Init 1 */

   /** Initialize RTC Only
   */
   hrtc.Instance = RTC;
   hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
   hrtc.Init.OutPut = RTC_OUTPUTSOURCE_ALARM;
   if (HAL_RTC_Init(&hrtc) != HAL_OK)
   {
     Error_Handler();
   }
 
   /* USER CODE BEGIN Check_RTC_BKUP */
 
   /* USER CODE END Check_RTC_BKUP */
 
   /** Initialize RTC and set the Time and Date
   */
   sTime.Hours = 9;
   sTime.Minutes = 40;
   sTime.Seconds = 0;
 
   if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
   {
     Error_Handler();
   }
   DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
   DateToUpdate.Month = RTC_MONTH_JUNE;
   DateToUpdate.Date = 6;
   DateToUpdate.Year = 23;
 
   if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BIN) != HAL_OK)
   {
     Error_Handler();
   }
   /* USER CODE BEGIN RTC_Init 2 */
 
   /* USER CODE END RTC_Init 2 */
 
 }

 

  2. 在MX_RTC_Init函数的结尾,把0x7240这段数据写入BKP某个16位的寄存器里面,之后在MX_RTC_Init函数的开始写一个判断BKP某个寄存器是否为0x7240这段数据,如果条件为真则return出函数。这样就达到了初始化一次的效果了。

     (BKP的特性掉电不丢失,可以去查看手册)

    (0x7240这段数据可以写任意数,别太大了)

 

  以下是代码:

   MX_RTC_Init头

   /* USER CODE BEGIN Check_RTC_BKUP */
    /* 只初始化一次 */
     if( HAL_RTCEx_BKUPRead( &hrtc,RTC_BKP_DR1 ) == 0x7240 )
     {
         return ;
     }
 
   /* USER CODE END Check_RTC_BKUP */

 

  MX_RTC_Init尾

 HAL_RTCEx_BKUPWrite( &hrtc,RTC_BKP_DR1,0x7240 );  

  2.  掉电丢失的问题二

  f103的RTC日期是不保存的,我门可以利用定时器中断来计数保存数据,代码如下:

  1. 开启RTC定时器

  2.  在stm32f1xx_it.c里面写,中断后存数据到指定BKP寄存器

/**
  * @brief This function handles RTC global interrupt.
  */
void RTC_IRQHandler(void)
{
  /* USER CODE BEGIN RTC_IRQn 0 */

  /* USER CODE END RTC_IRQn 0 */
    HAL_RTCEx_RTCIRQHandler(&hrtc);
  /* USER CODE BEGIN RTC_IRQn 1 */
    HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR2,hrtc.DateToUpdate.Year);
    HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR3,hrtc.DateToUpdate.Month);
    HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR4,hrtc.DateToUpdate.Date);
  /* USER CODE END RTC_IRQn 1 */
}

 

 

   3. rtc.c的HAL_RTC_MspInit函数内写

 __HAL_RTC_ALARM_ENABLE_IT(&hrtc,RTC_IT_SEC);  

  4. 读BKP寄存器的日期数据到计时变量内

    /* 只初始化一次 */
    if( HAL_RTCEx_BKUPRead( &hrtc,RTC_BKP_DR1 ) == 0x7240 )
    {
        /* 读BKP寄存器的日期数据到计时变量内 */
        hrtc.DateToUpdate.Year =  HAL_RTCEx_BKUPRead( &hrtc,RTC_BKP_DR2 );
        hrtc.DateToUpdate.Month =  HAL_RTCEx_BKUPRead( &hrtc,RTC_BKP_DR3 );
        hrtc.DateToUpdate.Date =  HAL_RTCEx_BKUPRead( &hrtc,RTC_BKP_DR4 );

        HAL_RTC_GetTime( &hrtc, &sTime, RTC_FORMAT_BIN );
        return ;
    }

 

 

这样就达到了日期存储的功能了。

以下是代码下载链接:

 

posted @ 2023-06-01 09:52  尘余  阅读(526)  评论(0编辑  收藏  举报