2024-02-20 08:25 PM - last edited on 2024-02-20 11:54 PM by Peter BENSCH
In my app, I need MCU to go to stop mode and then wake up by RTC timer.
I follow this RTC wake up example and manage to make MCU go to stop mode for a few seconds and then wake up.
Because in my app, we want MCU to wake up once in a few hours instead of a few seconds. The problem occurs when I try to increase the counter by 1000 times, the stop mode duration is still a few seconds.
Can someone enlighten me what the issue is? Does the time counter have limit? It is an unsigned 32 bit integer, which can be very large. Or is it constrained by hardware?
Solved! Go to Solution.
2024-02-21 02:39 AM - edited 2024-02-21 02:41 AM
If you are using CubeMX, you can set the Wake Up Clock to RTCCLK / 16 ... / 2, but also to 1 Hz and 1 Hz with 1 bit added to Wake Up Counter.
However, I see in your code that you call HAL_RTCEx_SetWakeUpTimer_IT manually in USER CODE 3, which is not really necessary. If you want this to remain manual, you would have to use
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // 1Hz
instead of
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16); // 2kHz
The wakeup timer is not a variable, but a hardware resource and defined uint32_t, because 17bit can also be set for 0.5Hz:
HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock);
2024-02-20 11:41 PM - edited 2024-02-20 11:46 PM
Although you have not inserted any code that would allow us to see what you have set incorrectly, you have probably encountered an overflow.
Background: the wake-up timer of the RTC not only has a prescaler of 16, but can usually be set in a wide range. In the given example, LSE is used as the clock, so that the prescaler of 16 results in an input frequency at the wake-up timer of 32kHz/16 = 2kHz. Incidentally, the wake-up timer does not have 32 bits, but only 16 bits, so that a maximum wake-up time of 32,768 seconds results at 2kHz.
Solution to your problem: instead of the prescaler of 16, simply use the option of 1Hz or 0.5Hz. At 1Hz you then get ~18.25h with 1s resolution, at 0.5Hz (1Hz with an additional bit) ~36.5h with 2s resolution.
[edit] Forgot to add that you can achieve ~9h wakeup time with the 32768 seconds when using the prescaler of 16, but larger values for the wakeup timer are truncated to 16bit. [/edit]
Does it answer your question?
Regards
/Peter
2024-02-21 12:18 AM
Below are my code. I bet you have solved my problem. Let me give it a try and then Accept it. Many thanks!
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};
/* 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 = 0x0;
sTime.Minutes = 0x0;
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_JANUARY;
sDate.Date = 0x1;
sDate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/** Enable the WakeUp
*/
if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_RTC_Init();
/* USER CODE BEGIN 2 */
sprintf(uart2_str, "\tRTC Timer Wakeup ...\n");
HAL_UART_Transmit(&huart2, (uint8_t *)uart2_str, strlen(uart2_str), 999);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
Blink_Led(250, 8);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
HAL_SuspendTick();
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
/* Enter STOP 2 mode */
memset(uart2_str, 0, 64);
sprintf(uart2_str, "\n\t\t *** OK Before Stop/Standby Mode\n");
HAL_UART_Transmit(&huart2, (uint8_t*)uart2_str, strlen(uart2_str), 999);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
SystemClock_Config();
HAL_ResumeTick();
memset(uart2_str, 0, 64);
sprintf(uart2_str, "\t\t *** OK Wake Up\n");
HAL_UART_Transmit(&huart2, (uint8_t*)uart2_str, strlen(uart2_str), 999);
Blink_Led(1000, 4);
}
/* USER CODE END 3 */
}
2024-02-21 02:21 AM
Two more questions:
2024-02-21 02:39 AM - edited 2024-02-21 02:41 AM
If you are using CubeMX, you can set the Wake Up Clock to RTCCLK / 16 ... / 2, but also to 1 Hz and 1 Hz with 1 bit added to Wake Up Counter.
However, I see in your code that you call HAL_RTCEx_SetWakeUpTimer_IT manually in USER CODE 3, which is not really necessary. If you want this to remain manual, you would have to use
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // 1Hz
instead of
HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16); // 2kHz
The wakeup timer is not a variable, but a hardware resource and defined uint32_t, because 17bit can also be set for 0.5Hz:
HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock);