Skip to main content

Command Palette

Search for a command to run...

STM32 RTC (Real Time Clock) Detailed Explanation

Updated
4 min read
STM32 RTC (Real Time Clock) Detailed Explanation

The Real-Time Clock (RTC) in STM32 microcontrollers is a critical peripheral for timekeeping applications. It operates independently from the main CPU, allowing it to maintain accurate time even in low-power modes. Below is a comprehensive guide to understanding and using the STM32 RTC.


1. RTC Overview

Key Features

  • Independent Power Domain: Can run from a backup battery (VBAT) when main power is off.

  • 32-bit Programmable Counter: Counts seconds, minutes, hours, etc.

  • Calendar Support: Day, month, year, and weekday tracking.

  • Alarms: Can trigger interrupts or wake the MCU from sleep.

  • Periodic Wakeup Unit: Useful for low-power applications.

  • Tamper Detection: Protects against unauthorized time changes.

Clock Sources

  • LSE (Low-Speed External): 32.768 kHz crystal (most accurate).

  • LSI (Low-Speed Internal): ~32 kHz RC oscillator (less accurate, no crystal needed).

  • HSE (High-Speed External): Divided down (rarely used for RTC).

📌 Recommendation: Use LSE for best accuracy (e.g., with a 32.768 kHz crystal).


2. RTC Registers & Functional Blocks

Main Components

  1. Prescaler

    • Divides the input clock (e.g., 32.768 kHz → 1 Hz for seconds counting).

    • Consists of:

      • Asynchronous Prescaler (PREDIV_A)

      • Synchronous Prescaler (PREDIV_S)

    • Example: For LSE = 32.768 kHz:

      • PREDIV_A = 127 → 256 Hz

      • PREDIV_S = 255 → 1 Hz

  2. Counter Register (RTC_CNT)

    • Holds the current time in binary format (typically Unix time or BCD).
  3. Alarm Registers (RTC_ALR)

    • Compare against RTC_CNT to trigger an alarm.
  4. Backup Registers (RTC_BKPxR)

    • Retain data during power loss (if VBAT is connected).

3. Initializing the RTC

Using STM32 HAL (STM32CubeMX)

  1. Enable RTC Clock & Power

    c

     __HAL_RCC_RTC_ENABLE();      // Enable RTC clock
     __HAL_RCC_PWR_CLK_ENABLE();  // Enable Power Control clock
     HAL_PWR_EnableBkUpAccess();  // Allow access to backup domain
    
  2. Configure Clock Source (LSE/LSI)

    c

     RCC_OscInitTypeDef RCC_OscInit = {0};
     RCC_OscInit.OscillatorType = RCC_OSCILLATORTYPE_LSE;
     RCC_OscInit.LSEState = RCC_LSE_ON;  // Enable LSE crystal
     HAL_RCC_OscConfig(&RCC_OscInit);
    
  3. Initialize RTC

    c

     RTC_TimeTypeDef sTime = {0};
     RTC_DateTypeDef sDate = {0};
    
     // Set time (24-hour format)
     sTime.Hours = 14;
     sTime.Minutes = 30;
     sTime.Seconds = 0;
     HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
    
     // Set date
     sDate.WeekDay = RTC_WEEKDAY_MONDAY;
     sDate.Month = RTC_MONTH_JANUARY;
     sDate.Date = 1;
     sDate.Year = 23;  // 2023
     HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN);
    

4. Reading Time & Date

c

RTC_TimeTypeDef currentTime;
RTC_DateTypeDef currentDate;

HAL_RTC_GetTime(&hrtc, &currentTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &currentDate, RTC_FORMAT_BIN);

printf("Time: %02d:%02d:%02d\n", currentTime.Hours, currentTime.Minutes, currentTime.Seconds);
printf("Date: %02d-%02d-20%02d\n", currentDate.Date, currentDate.Month, currentDate.Year);

5. Using RTC Alarms

Set an Alarm (Wake After 10 Seconds)

c

RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours = 0;
sAlarm.AlarmTime.Minutes = 0;
sAlarm.AlarmTime.Seconds = 10;  // Trigger after 10 sec
sAlarm.AlarmMask = RTC_ALARMMASK_NONE;  // Match all fields
sAlarm.Alarm = RTC_ALARM_A;             // Use Alarm A
HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN);

Handle Alarm Interrupt

c

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
    printf("Alarm triggered!\n");
}

6. Low-Power Operation

Wake from STOP Mode Using RTC Alarm

  1. Enter STOP Mode

    c

     HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    
  2. Configure RTC Wakeup

    c

     HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 10, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);  // Wake every 10 sec
    

7. Backup Domain & Tamper Detection

Retain Data During Power Loss

c

HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, 0x1234);  // Write to backup register
uint32_t data = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0);  // Read after reset

Enable Tamper Detection

c

RTC_TamperTypeDef sTamper = {0};
sTamper.Tamper = RTC_TAMPER_1;
sTamper.Trigger = RTC_TAMPERTRIGGER_RISINGEDGE;
HAL_RTCEx_SetTamper(&hrtc, &sTamper);

8. Common Issues & Fixes

ProblemSolution
RTC not keeping timeCheck LSE crystal & backup battery.
Alarm not triggeringVerify NVIC interrupts are enabled.
Time driftsCalibrate LSI or use LSE.
Backup data lostEnsure VBAT is connected.

9. Advanced Topics

  • RTC Smooth Calibration (Adjust for crystal inaccuracies).

  • Time Stamp (Record external events).

  • Digital Trimming (Fine-tune clock accuracy).


Conclusion

The STM32 RTC is a versatile peripheral for timekeeping, alarms, and wakeup events. Key steps:

  1. Initialize with LSE/LSI.

  2. Set/Read time and date.

  3. Use Alarms for interrupts.

  4. Enable Backup Domain for data retention.

More from this blog

A

Ampheo Electronic Blog-Chip and component knowledge sharing

181 posts

Original and Genuine Electronic Components Distributor