简体   繁体   中英

What RTC backup register should I use in STM32?

I'm using STM32F373 and I want to load the calender and clock every time I start up my STM32.

So I have connected Vbat to 3V via a coin battery and now I need to load my backup register after I have initialize the RTC structure.

This is an example from STM32 Repository for STM32F373

 /*##-1- Configure the RTC peripheral #######################################*/
  /* Configure RTC prescaler and RTC data registers */
  /* RTC configured as follows:
      - Hour Format    = Format 24
      - Asynch Prediv  = Value according to source clock
      - Synch Prediv   = Value according to source clock
      - OutPut         = Output Disable
      - OutPutPolarity = High Polarity
      - OutPutType     = Open Drain */ 
  RtcHandle.Instance = RTC; 
  RtcHandle.Init.HourFormat = RTC_HOURFORMAT_24;
  RtcHandle.Init.AsynchPrediv = RTC_ASYNCH_PREDIV;
  RtcHandle.Init.SynchPrediv = RTC_SYNCH_PREDIV;
  RtcHandle.Init.OutPut = RTC_OUTPUT_DISABLE;
  RtcHandle.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  RtcHandle.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;

  if (HAL_RTC_Init(&RtcHandle) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler();
  }
  
  /* Turn on LED1 */
  BSP_LED_On(LED1);

  /*##-2- Check if Data stored in BackUp register1: No Need to reconfigure RTC#*/
  /* Read the Back Up Register 1 Data */
  if (HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR1) != 0x32F2)
  {
    /* Configure RTC Calendar */
    RTC_CalendarConfig();
  }
  else
  {
    /* Check if the Power On Reset flag is set */
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET)
    {
      /* Turn on LED2: Power on reset occurred */
      BSP_LED_On(LED2);
    }
    /* Check if Pin Reset flag is set */
    if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST) != RESET)
    {
      /* Turn on LED4: External reset occurred */
      BSP_LED_On(LED4);
    }
    /* Clear source Reset Flag */
    __HAL_RCC_CLEAR_RESET_FLAGS();
  }

The interesting part here is

if (HAL_RTCEx_BKUPRead(&RtcHandle, RTC_BKP_DR1) != 0x32F2)

From the data sheet

在此处输入图像描述

Question:

What backup register should I read? Is it RTC_BKP_DR0, RTC_BKP_DR1, RTC_BKP_DR2, RTC_BKP_DR3 etc?

The function HAL_RTCEx_BKUPRead says that the backup register goes from 0 to 19.

What return value should I except?

/**
  * @brief  Reads data from the specified RTC Backup data Register.
  * @param  hrtc RTC handle
  * @param  BackupRegister RTC Backup data Register number.
  *          This parameter can be: RTC_BKP_DRx where x can be from 0 to 19 to
  *                                 specify the register.
  * @retval Read value
  */
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
{
  uint32_t tmp = 0U;

  /* Check the parameters */
  assert_param(IS_RTC_BKP(BackupRegister));

  tmp = (uint32_t) & (hrtc->Instance->BKP0R);
  tmp += (BackupRegister * 4U);

  /* Read the specified register */
  return (*(__IO uint32_t *)tmp);
}

The backup registers have no purpose assigned in hardware, they are just battery backed-up memory that the application can use however you please.

However, if you choose to use the HAL library, it uses one of your backup registers for its own purpose: it writes a magic value into the register when it sets up the clock. Then, after reboot, if it finds the same magic value it know that the clock is already set up and does not re-initialize it.

If you want to re-initialize the clock every boot then you do not need the backup registers at all, and you should change the above code to always call the init function.

@Heretic As Tom said, those 0-19 backup registers (each one is 32bits) don't do nothing for your "TIME". They're there just for the user to save some data, for example you can save a temperature or some other data. If you want to save time, it's what I've done:

  1. I save time (I get it from a server, you can use buttons or anything to set the time) like this:
    
    RTC_TimeTypeDef sTime = {0};
    RTC_DateTypeDef sDate = {0};
    
    sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
    sTime.StoreOperation = RTC_STOREOPERATION_RESET;
    sTime.Hours = time.ntp_hour;
    sTime.Minutes = time.ntp_minute;
    sTime.Seconds = time.ntp_second;
    sTime.SubSeconds = time.ntp_subsec;
    sDate.WeekDay = time.ntp_week_day;
    sDate.Month = time.ntp_month;
    sDate.Date = time.ntp_date;
    sDate.Year = time.ntp_year;
    
    HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
    HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
    HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, '*'); //I use one of the backup registers to remember that I've set time. I simply write an '*' on it!
    
  1. The next time that rtc is loading, I check if I have time:

/* 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 sDate = {0};
  RTC_AlarmTypeDef sAlarm = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* 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.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */
    if(HAL_RTCEx_BKUPRead(&hrtc, BKP_INITIATED_ADDRESS) == '*') {
        //Time is OK. Set Alarms later.
        printf("RTC backup available\n");
        return;
    }
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */


//I didn't copy the rest of this function to make is shorter.

}

This is it. I use a backup register to remember that I have time, and check it. I DO NOT save time in any 0-19 register manually.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM