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 ;    }

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

以下是代码下载链接: