2026-03-05 2:53 AM - last edited on 2026-03-05 5:22 AM by Imen.D
Hello.
I'm having a problem with an STM32H503.
I need to use the RTC, which is running on the internal 32kHz LSI clock.
The clock configuration was created with CubeMX.
When I check the RTC, I see that it has only advanced by 21 seconds in 60 seconds. That's a deviation of 285%.
The processor is running on the HSI clock, which is divided by 2, so 32MHz.
Does anyone know why the RTC is running 3 times too slow?
Init of the RCC:
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI | RCC_OSCILLATORTYPE_LSI;
RCC_OscInitStruct.HSIState = RCC_HSI_ON;
RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV2;
RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; // RCC_PLL_OFF;
if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
{
Error_Handler();
}
/** Initializes the CPU, AHB and APB buses clocks
*/
RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2
| RCC_CLOCKTYPE_PCLK3;
RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSI;
RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
RCC_ClkInitStruct.APB3CLKDivider = RCC_HCLK_DIV1;
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK)
{
Error_Handler();
}
Init of the RTC:
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 999; // 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.backupRegisterPrivZone = RTC_PRIVILEGE_BKUP_ZONE_NONE;
privilegeState.backupRegisterStartZone2 = RTC_BKP_DR0;
privilegeState.backupRegisterStartZone3 = RTC_BKP_DR0;
if (HAL_RTCEx_PrivilegeModeSet(&hrtc, &privilegeState) != HAL_OK)
{
Error_Handler();
}
/** Enable the WakeUp
* should be 100ms
*/
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, (100) , RTC_WAKEUPCLOCK_RTCCLK_DIV16, 0) != HAL_OK)
{
Error_Handler();
}
Solved! Go to Solution.
2026-03-05 2:57 AM - edited 2026-03-05 2:58 AM
If you increase the prescaler cca 3x, the counter is going to run cca 3x slower
hrtc.Init.SynchPrediv = 999; // 255;
Okay, it's more like 4x, but the point is the same. LSI is very imprecise, that explains the 3x/4x difference.
JW
2026-03-05 2:57 AM - edited 2026-03-05 2:58 AM
If you increase the prescaler cca 3x, the counter is going to run cca 3x slower
hrtc.Init.SynchPrediv = 999; // 255;
Okay, it's more like 4x, but the point is the same. LSI is very imprecise, that explains the 3x/4x difference.
JW
2026-03-05 3:23 AM
Thank you.
I've tryed to get milliseconds resolution with the RTC
2026-03-05 4:42 AM
Well, you can, but if you still want the RTC itself to measure real time (at least roughly), you have to change the asynchronous prescaler's value simultaneously with the synchronous one, so that multiplying them (after adding 1) results in the oscillator's frequency. Say the LSI runs at 40kHz, so you have to set the asynchronouos prescaler to 40-1 while synchronous to 1000-1.
With a precise 32.768kHz LSE you can't achieve exact 1ms, though. With LSI, the result is as imprecise as LSI itself is.
JW