打印
[STM32U5]

【NUCLEO-U5A5ZJ-Q测评】超简单的RTC实验

[复制链接]
1027|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lulugl|  楼主 | 2023-11-13 17:11 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
#申请原创#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
【前言】
STM32U5A5带有RTC(实时时钟),RTC是个独立的定时器。RTC模块拥有一个连续计数的计数器,在相应的软件配置下,可以提供时钟日历的功能。修改计数器的值可以重新设置当前时间和日期 RTC还包含用于管理低功耗模式的自动唤醒单元。stm32CubeIDE可以轻松的帮开发者配置相关的代码。本实验只实现时间的读取与展示。
【开发环境】
win11
Stm32CubeIDE 1.13版本
【开发板】
NUCLEO-U5A5ZJ-Q
ILI9488LCD屏
【工程创建】
1、设置RCC

  • 设置高速外部时钟HSE 选择外部时钟源
  • 使能外部晶振LSE

RTC设备因为其独特的运行方式(即掉电依旧运行)使用HSE分频时钟或者LSI的时候,在主电源VDD掉电的情况下,这两个时钟来源都会受到影响,资源消耗太大,小小的纽扣电池根本吃不消。没法保证RTC正常工作.所以RTC一般都时钟低速外部时钟LSE。
2、配置RTC

  • Activate Clock Source 激活时钟源
  • Activate calendar激活日历


设置时、分、秒,以及年月日,这里我们需要设置为BCD模式。
3、设置外部低速时钟输入。

按alt+k重新生成工程,在freertos任务中添加时钟的读取与显示功能:
/* USER CODE END Header_StartTask02 */
void StartTask02(void *argument)
{
  /* USER CODE BEGIN myTask02 */
  uint8_t show_str[20];
  uint8_t show_data[20];
  uint8_t show_time[20];
  uint32_t mytick;
  RTC_DateTypeDef GetData;  //获取日期结构�?

  RTC_TimeTypeDef GetTime;   //获取时间结构�?

  /* Infinite loop */
  for(;;)
  {
          mytick = HAL_GetTick();
          sprintf(show_str,"run times:%d",mytick/1000);
          ILI9488_printText(show_str,10,40,ILI9488_BLACK,ILI9488_WHITE,2);
          /* Get the RTC current Time */
          HAL_RTC_GetTime(&hrtc, &GetTime, RTC_FORMAT_BIN);
      /* Get the RTC current Date */
      HAL_RTC_GetDate(&hrtc, &GetData, RTC_FORMAT_BIN);
      sprintf(show_data, "%04d/%02d/%02d",2000 + GetData.Year, GetData.Month, GetData.Date);
      ILI9488_printText(show_data,10,60,ILI9488_BLACK,ILI9488_WHITE,2);
      sprintf(show_time, "%02d:%02d:%02d",GetTime.Hours, GetTime.Minutes, GetTime.Seconds);
      ILI9488_printText(show_time,10,80,ILI9488_BLACK,ILI9488_WHITE,2);

    osDelay(1000);
  }
  /* USER CODE END myTask02 */
}

【RTC掉电重置】
但是呢,在hal库中生成的代码,每次断电就RTC时间会重置,每次上电都会重新初始化时间因为HAL库设置了一个BKP寄存器保存一个标志。每次单片机启动时都读取这个标志并判断是不是预先设定的值:如度果不是就初始化RTC并设置时间,再设置标志为预期值;如果是预期值就跳过初始化和时间设置,继续执行后面的程序
所以这里我们只需要每次上电执行RTC初始化之前,将标志设置为预期值即可。
为止,在rtc.c中的RTC_init修改为以下内容,即可以实现该功能。
/* RTC init function */
void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */
        RTC_TimeTypeDef time;   //时间结构体参�?
        RTC_DateTypeDef datebuff;   //日期结构体参�?
  /* USER CODE END RTC_Init 0 */

  RTC_PrivilegeStateTypeDef privilegeState = {0};
  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};

  /* USER CODE BEGIN RTC_Init 1 */
  __HAL_RCC_PWR_CLK_ENABLE();                  //�?启电源时�?
  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
  hrtc.Init.BinMode = RTC_BINARY_NONE;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }
  privilegeState.rtcPrivilegeFull = RTC_PRIVILEGE_FULL_NO;
  privilegeState.rtcPrivilegeFeatures = RTC_PRIVILEGE_FEATURE_INIT;
  privilegeState.backupRegisterPrivZone = RTC_PRIVILEGE_BKUP_ZONE_1;
  privilegeState.backupRegisterStartZone2 = RTC_BKP_DR0;
  privilegeState.backupRegisterStartZone3 = RTC_BKP_DR0;
  if (HAL_RTCEx_PrivilegeModeSet(&hrtc, &privilegeState) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
  if(HAL_RTCEx_BKUPRead(&hrtc,RTC_BKP_DR1)!= 0x5051)
          {

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x16;
  sTime.Minutes = 0x6;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_NOVEMBER;
  sDate.Date = 0x13;
  sDate.Year = 0x23;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */
          datebuff = sDate;  //把日期数据拷贝到自己定义的data�?
          HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, 0x5051);//向指定的后备区域寄存器写入数�?
          HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, (uint16_t)datebuff.Year);
          HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, (uint16_t)datebuff.Month);
          HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, (uint16_t)datebuff.Date);
          HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, (uint16_t)datebuff.WeekDay);

    }
          else
          {
                  datebuff.Year    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
                  datebuff.Month   = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3);
                  datebuff.Date    = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);
                  datebuff.WeekDay = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5);
                  sDate = datebuff;
                  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
                  {
                          Error_Handler();
                  }

          }

  /* USER CODE END RTC_Init 2 */

}
【实验效果】


使用特权

评论回复
沙发
vivilyly| | 2023-12-12 15:00 | 只看该作者
使用hal不能保存年月日参数怎么办?

使用特权

评论回复
板凳
lulugl|  楼主 | 2023-12-12 15:23 | 只看该作者
vivilyly 发表于 2023-12-12 15:00
使用hal不能保存年月日参数怎么办?

可以的呀,可以保存到RTC备用寄存器。

使用特权

评论回复
地板
jf101| | 2023-12-13 22:46 | 只看该作者
是不是使用电池掉电就不会重置了

使用特权

评论回复
5
lulugl|  楼主 | 2023-12-13 23:05 | 只看该作者
jf101 发表于 2023-12-13 22:46
是不是使用电池掉电就不会重置了

有电池,他就不会重置。象电脑的BIOS一样

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

145

主题

713

帖子

9

粉丝