RTC i STM32 - Hur vilka backup-register ska man välja?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av DanielM »

Min RTC är aktiv så länge Vbat är ansluten till ungefär 3V. Det betyder att trots att Vdd = 0 volt så kommer RTC:n fortfarande att ticka på. Så vill jag ha det.
Vid start hos min STM32 så initialiserar jag min RTC. Som ni ser så skriver jag över nuvarande datum och tid till 2000-01-01 00:00:00. Så vill jag inte ha det, om Vbat är ansluten till en strömkälla.

Kod: Markera allt

static 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 */
 
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0;
  sTime.Minutes = 0;
  sTime.Seconds = 0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 1;
  sDate.Year = 0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable the Alarm A
  */
  sAlarm.AlarmTime.Hours = 0;
  sAlarm.AlarmTime.Minutes = 0;
  sAlarm.AlarmTime.Seconds = 0;
  sAlarm.AlarmTime.SubSeconds = 0;
  sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 1;
  sAlarm.Alarm = RTC_ALARM_A;
  if (HAL_RTC_SetAlarm(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
  {
    Error_Handler();
  }
  /** Enable the Alarm B
  */
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;
  sAlarm.Alarm = RTC_ALARM_B;
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}
Enligt STM32 Repository för STM32F373 serien så finns det ett exempel för RTC.

Kod: Markera allt

/*##-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();
  }

Det är denna if-sats som är intressant.

Kod: Markera allt

  /*##-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();
  }
Tittar man i databladet så får man egentligen ingen information om alla bitar. Det står bara "backup register".
Skärmklipp.PNG
Tittar man i koden för HAL_RTCEx_BKUPRead så står det så här:

Kod: Markera allt

/**
  * @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);
}
Det betyder att jag skulle kunna avgöra om Vbat är anslutet till en strömkälla. Om fallet är JA, då behöver jag inte ändra tiden till 2000-01-01 00:00:00 vid start av min STM32.

Kod: Markera allt

 /* 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, RTC_BKP_DR0) == 0x32F2)
	  return;
  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
Då är frågan:

Det finns RTC_BKP_DR0 till RTC_BKP_DR19. Vilken ska jag ha?
Med hjälp utav HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0), vad ska jag då anta vad funktionen kommer returnera tillbaka så jag kan avgöra om Vbat är aktiv eller inte?
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av Micke_s »

Du kan inte avgöra om vbat finns från DRx registret.
Du kan avgöra om RTC DRx registret har ”reset state” eller ej. Välj valfritt DR reg
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av DanielM »

Okej. Om jag väljer då som exemplet ovan visar, vad ska jag förvänta mig att funktionen returnerar tillbaka då? Är det detta tal 0x32F2 ?
Eller menar du att jag kan använda vilket returnerbart värde som möjligt?

Alltså så här

Kod: Markera allt

  const uint32_t return_value = 0xFFFF;
  if(HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0) == return_value)
	  return;
  else
	  HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, return_value);
Senast redigerad av DanielM 19 september 2021, 16:41:29, redigerad totalt 1 gång.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av Micke_s »

0x32F2 skriver du i registret när du är klar med din RTC init, sedan finns detta värde kvar så länge någon av VBAT eller VDD är kvar…
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av DanielM »

Ändrade mitt inlägg. Jag förstod vad du menar.

Jag tolkade först att backup-register ändrades hela tiden när Vdd = 0. Men tydligen så verkar det vara någon intern liten "hårddisk" som lever kvar så länge Vbat eller Vdd är minst 3 volt.

Ska kolla om det fungerar nu.

Edit:
Ja den kommer ihåg minnet nu. Men RTC klockan stannar endast. Inte att den fortsätter att räkna. Troligtvis har det med att RTC:n kanske inte tickar på när Vdd = 0?
Ska undersöka om jag har valt rätt kristall i CubeMX.

Nix. LSI och HSE ger samma resultat. RTC klockan stannar när Vdd är 0 volt. Men båda kommer ihåg tiden och HSE räknar för snabbt.

Edit2:


Okej. Måste ha LSE aktiverad. Måste köpa kristall då. Dyrt med frakt. Någon som rekommenderar någon inrikes 32.768 kHz kristallförsäljare som kan sälja kristaller med formatet SMD_2012-2Pin_2.0x1.2mm ?
Skärmklipp.PNG
Jag har två stycken utav dessa
https://eu.mouser.com/ProductDetail/Eps ... AKdVirMQ==

Men jag vet inte hur kvalitén är på dom. Jag fick nämligen inte dom att fungera förra gången så jag tog bort dom.
Dom är dessutom rekommenderade av ST.
Skärmklipp.PNG
Jag funderar på alltså välja en annan kristall.
Skärmklipp.PNG
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Användarvisningsbild
Micke_s
EF Sponsor
Inlägg: 6741
Blev medlem: 15 december 2005, 21:31:34
Ort: Malmö

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av Micke_s »

Tips att skriva värdet efter all RTC setup.

Finns risk annars att något händer efter skrivningen till DR som gör att din RTC kod ej köra..
DanielM
Inlägg: 2166
Blev medlem: 5 september 2019, 14:19:58

Re: RTC i STM32 - Hur vilka backup-register ska man välja?

Inlägg av DanielM »

Det ska jag tänka på.

Just nu så ändrades inte värdet. Men jag måste införskaffa en LSE kristall för att RTC:n ska ticka på när Vdd är 0. Men tack för hjälpen i alla fall =)
Skriv svar