STM32: internal RTC, clock and battery backup (VBAT)

Spread the love

Welcome to our comprehensive article on the STM32’s internal Real-Time Clock (RTC), clock system, and battery backup (VBAT). In today’s fast-paced world, precise timekeeping and effective power management are essential elements of modern embedded systems. The STM32 family of microcontrollers, with their feature-rich capabilities, offers an excellent solution to address these requirements.

STM32: internal RTC clock and battery backup (VBAT)
STM32: internal RTC clock and battery backup (VBAT)

A real-time clock (RTC) is a computer clock that keeps track of the current time. The microcontrollers supporting the RTC can be used for chronometers, alarm clocks, watches, small electronic agendas, and many other devices.

In the STM32, the real-time clock (RTC) is an independent BCD timer/counter. Dedicated registers contain the second, minute, hour (in 12/24 hour), weekday, date, month, year in BCD (binary-coded decimal) format. Correction for 28, 29 (leap year), 30, and 31 days of the month are performed automatically. The RTC features a reference clock detection, a more precise second source clock (50 or 60 Hz) can be used to enhance the calendar precision. The RTC provides a programmable alarm and programmable periodic interrupts with wakeup from Stop and Standby modes

VBAT operation is activated when VDD is not present. A symbiotic element is the VBAT pin, which allows the power of the device VBAT domain from an external battery, an external super-capacitor, or from VDD when no external battery and an external super-capacitor are present. The VBAT pin supplies the RTC and the backup registers.

Detail

This RTC can be used with three clock sources:

  • HSE is a high-speed external clock, which can be connected with a quartz/ceramic resonator or external clock source. Its frequency range is from 4MHz to 16MHz.
    The high-speed external oscillator provides a safe crystal system clock. A clock security system allows automatic detection of HSE failure. In this case, a Non-Maskable Interrupt is generated, and a broken input can be sent to timers in order to put critical applications such as motor control in a safe state. When an HSE failure is detected, the HSE oscillator is automatically disabled. If HSE is selected directly or indirectly (PLLRCLK selected for SYSCLK and HSE selected as PLL input) as the system clock, and a failure of the HSE clock is detected, the system clock switches automatically to HSISYS, so the application software does not stop in case of a crystal oscillator failure. The OSC_OUT pin can be used as GPIO, or it can be configured as an OSC_EN alternate function to provide a signal enabling the stop of the external clock synthesizer when the device enters low-power modes.
  • LSI is a low-speed internal clock RC oscillator, with a frequency of 40 kHz, providing a low-power clock. STM32 devices embed an ultra-low-power RC oscillator, which is available in all modes except Shutdown and VBAT. The LSI can be used to clock the RTC, the low-power timers, and the independent watchdog. The LSI consumption is typically 110 nA. 
  • LSE is a low-speed external clock connected to 32.768 kHz quartz crystal. The low-speed external oscillator can be used with external quartz or resonator, or with an external clock source in Bypass mode. The oscillator driving capability is programmable. Four modes are available, from an ultra-low power mode with a consumption of only 250 nano amperes to a high-driving mode. A clock security system monitors for the failure of the LSE oscillator. If LSE is used as a system clock, and a failure of the LSE clock is detected, the system clock switches automatically to LSI. The CSS is functional in all modes except Shutdown and VBAT. It is also functional under reset. The LSE can be used to clock the RTC, the CEC, the USARTs or low-power UART peripherals, and the low-power timers.

We do not mention HSI or other oscillators because they are not used with RTC.

We are going to use for the test a generic STM32F103 blue pill (STM32F4 black pill is quite similar, only CPU freq change), and you can see in the schematic shared on the specified device that has a 4-to-16 MHz crystal oscillator internally connected to PD0 and PD1 to manage HSE.

STM32F1 blue pill: 4-to-16 MHz crystal oscillator internally connected
STM32F1 blue pill: 4-to-16 MHz crystal oscillator internally connected

And a 32 kHz oscillator for RTC with calibration connected to PC14 and PC15 is used for LSE.

STM32F1 blue pill: 32 kHz oscillator for RTC on PC14 and PC15
STM32F1 blue pill: 32 kHz oscillator for RTC on PC14 and PC15

So the complete schema becomes.

RTC Clock schema of STM32F103 blue pill
RTC Clock schema of STM32F103 blue pill

You can see an HSI RC also, but we must pay attention only to the RTC part of the schema.

RTC Clock source selection
RTC Clock source selection

Battery backup

As you can see in the pinout diagram, there is a VBAT pin.

Pinout STM32 STM32F1 STM32F103 STM32F103C8 low resolution
Pinout STM32 STM32F1 STM32F103 STM32F103C8 low resolution

Normal battery

The simplest method to preserve the RTC status is to connect directly to a cr2032 battery.

Pay attention that the cr2032 has 3.6v, so if you are going to use a LIR2032, remember that It has 4.2v at max charge, and It isn’t a good idea.

Select cr2032 5.5V Super Capacitor - ML2032 - cr2032 - Rechargeable AA and AAA

STM32 RTC VBAT: battery schema
STM32 RTC VBAT: battery schema

You can also use a 2xAA battery or similar, and the accepted range is 1.55v to 3.6v.

Rechargeable battery

Another good solution is to use a rechargeable battery (NiMH, NiCd, Li-ion, or Lipo cells), you can also provide a recharge system like the schema given by ST.

The NiMH AA battery can be a solution.

STM32 RTC battery rechargeable 2xAA breadboard
STM32 RTC battery rechargeable 2xAA breadboard

But I think the AA is quite big, so you can use an ML2032, a rechargeable battery at 3v that works from 3.2v to 2.6v.

STM32 RTC VBAT: battery rechargeable ml2032 on breadboard
STM32 RTC VBAT: battery rechargeable ml2032 on a breadboard

As you can understand, the size and the amperage of the battery depend on your needs, like duration and package size.

STM32 RTC: battery rechargeable schema
STM32 RTC: battery rechargeable schema

Select ml2032 and Rechargeable AA and AAA 5.5V Super Capacitor - ML2032 - cr2032 - Rechargeable AA and AAA

Super-capacitor

Another good solution is the classic super-capacitor.

STM32 RTC VBAT: super-capacitor on breadboard
STM32 RTC VBAT: super-capacitor on breadboard

the ST advises a capacitor from 0.22F to 1F.

STM32 RTC VBVAT: super-capacitor schema
STM32 RTC VBVAT: super-capacitor schema

Select the super-capacitor 5.5V Super Capacitor - ML2032 - cr2032 - Rechargeable AA and AAA

Library

To interface the internal clock we can use the STM32RTC library, which offers a good quantity of functions.

And you can download It from the Arduino library manager.

Arduino library manager: STM32 RTC
Arduino library manager: STM32 RTC

Basic sketch

STM32: VBAT pin used with cr2032 for RTC backup
STM32: VBAT pin used with cr2032 for RTC backup

We use the default LSI without going in deep with the other modality, but paying attention to the schema, becomes very important when managing low-power management.

/**
 * Simple example of RTC Clock for STM32
 * You can use Serial to pass an epoch time that 
 * synchronize the clock
 * 
 * To generate epoch you can use browser console and input
 * Math.round(new Date().getTime()/1000)
 * 
 * @author  Renzo Mischianti (www.mischianti.org)
 * @brief 
 * @version 0.1
 * @date 2022-04-06
 * 
 */
#include <Arduino.h>
#include <STM32RTC.h>

/* Get the rtc object */
STM32RTC& rtc = STM32RTC::getInstance();

/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 0;
const byte hours = 16;

/* Change these values to set the current initial date */
/* Monday 15th June 2015 */
const byte weekDay = 1;
const byte day = 15;
const byte month = 6;
const byte year = 15;

void setup()
{
  Serial.begin(115200);

  // Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
  // By default the LSI is selected as source.
  //rtc.setClockSource(STM32RTC::LSE_CLOCK);

  rtc.begin(); // initialize RTC 24H format

  // // Set the time
  // rtc.setHours(hours);
  // rtc.setMinutes(minutes);
  // rtc.setSeconds(seconds);

  // // Set the date
  // rtc.setWeekDay(weekDay);
  // rtc.setDay(day);
  // rtc.setMonth(month);
  // rtc.setYear(year);

  // // you can use also
  // //rtc.setTime(hours, minutes, seconds);
  // //rtc.setDate(weekDay, day, month, year);
}

long startTime = millis();
long interval = 5000;

void loop()
{
  if (startTime+interval<millis()){
    // Print date...
    Serial.printf("%02d/%02d/%02d ", rtc.getDay(), rtc.getMonth(), rtc.getYear());

    // ...and time
    Serial.printf("%02d:%02d:%02d.%03d\n", rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds());
    startTime = millis();
  }
  if (Serial.available()){
    long epoch =  String(Serial.readString()).toInt();
    rtc.setEpoch(epoch);
    Serial.println(epoch);
  }
}

Here is the Serial output.

01/01/00 00:00:42.000
01/01/00 00:00:47.000
01/01/00 00:00:52.000
01/01/00 00:00:57.000
01/01/00 00:01:02.000
01/01/00 00:01:07.000

>>Send to COM35: "1649312899"<<
1649312899
07/04/22 06:28:19.000
07/04/22 06:28:24.000
07/04/22 06:28:29.000
07/04/22 06:28:34.000
07/04/22 06:28:39.000

If you disconnect the programmer cable and USB without disconnecting the backup battery, reconnect all and examine the output; you can check that the time was preserved.

Sketch: manage alarm

STM32 VBAT pin used with 2xAA batteries for RTC backup
STM32 VBAT pin used with 2xAA batteries for RTC backup

The STM32 provide a set of registers to store alarm and manage interrupt, we are going to examine a simple alarm.

/**
 * A simple sketch that set the time to 
 * 2022-04-20 at 16:00:00
 * and an alarm at
 * 16:00:10
 * the result is the interrupt after 10 secs
 * 
 * @author Renzo Mischianti <www.mischianti.org>
 * @version 0.1
 * @date 2022-04-07
 * 
 * @copyright Copyright (c) 2022
 * 
 */

#include <STM32RTC.h>

/* Get the rtc object */
STM32RTC& rtc = STM32RTC::getInstance();

/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 0;
const byte hours = 16;

/* Change these values to set the current initial date */
const byte day = 20;
const byte month = 4;
const byte year = 22;

void alarmMatch(void *data);

void setup()
{
  Serial.begin(115200);

  // Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
  // By default the LSI is selected as source.
  //rtc.setClockSource(STM32RTC::LSE_CLOCK);

  rtc.begin(); // initialize RTC 24H format

  // we set the time at 2022-04-20 at 16:00:00
  rtc.setTime(hours, minutes, seconds);
  rtc.setDate(day, month, year);

  rtc.attachInterrupt(alarmMatch);
  rtc.setAlarmDay(day);

  // Now we set an alert at 16:00:10 
  // pratically 10 secs after the start 
  // (check the initialization of clock)
  rtc.setAlarmTime(16, 0, 10, 0);
  rtc.enableAlarm(rtc.MATCH_DHHMMSS);
}

void loop()
{
  // Print date...
  Serial.printf("%02d/%02d/%02d ", rtc.getDay(), rtc.getMonth(), rtc.getYear());

  // ...and time
  Serial.printf("%02d:%02d:%02d.%03d\n", rtc.getHours(), rtc.getMinutes(), rtc.getSeconds(), rtc.getSubSeconds());
  delay(1000);
}

void alarmMatch(void *data)
{
  UNUSED(data);
  Serial.println("Alarm Match!");
}

And here is the Serial output.

20/04/22 16:00:05.000
20/04/22 16:00:06.000
20/04/22 16:00:07.000
20/04/22 16:00:08.000
20/04/22 16:00:09.000
20/04/22 16:00:10.000
Alarm Match!
20/04/22 16:00:11.000
20/04/22 16:00:12.000
20/04/22 16:00:13.000
20/04/22 16:00:14.000
20/04/22 16:00:15.000
20/04/22 16:00:16.000
20/04/22 16:00:17.000

Thanks

  1. STM32F1 Blue-Pill: pinout, specs, and Arduino IDE configuration (STM32duino and STMicroelectronics)
  2. STM32: program (STM32F1) via USB with STM32duino bootloader
  3. STM32: programming (STM32F1 STM32F4) via USB with HID boot-loader
  4. STM32F4 Black-Pill: pinout, specs, and Arduino IDE configuration
  5. STM32: ethernet w5500 with plain HTTP and SSL (HTTPS)
  6. STM32: ethernet enc28j60 with plain HTTP and SSL (HTTPS)
  7. STM32: WiFiNINA with ESP32 WiFi Co-Processor
    1. STM32F1 Blue-pill: WiFi shield (WiFiNINA)
    2. STM32F4 Black-pill: WiFi shield (WiFiNINA)
  8. How to use SD card with stm32 and SdFat library
  9. \STM32: SPI flash memory FAT FS
  10. STM32: internal RTC, clock, and battery backup (VBAT)
  11. STM32 LoRa
    1. Unleashing IoT Potential: Integrating STM32F1 Blue-Pill with EByte LoRa E32, E22, and E220 Shields
    2. Unleashing IoT Potential: Integrating STM32F4 Black-Pill with EByte LoRa E32, E22, and E220 Shields
  1. STM32 Power saving
    1. STM32F1 Blue-Pill clock and frequency management
    2. STM32F4 Black-Pill clock and frequency management
    3. Intro and Arduino vs STM framework
    4. Library LowPower, wiring, and Idle (STM Sleep) mode
    5. Sleep, deep sleep, shutdown, and power consumption
    6. Wake up from RTC alarm and Serial
    7. Wake up from the external source
    8. Backup domain intro and variable preservation across reset
    9. RTC backup register and SRAM preservation


Spread the love

4 Responses

  1. Ian says:

    I need this but programmed in STM32IDE using C. I dont know where to see the output anyways..

  2. pr1 says:

    How to catch pulses while powered by coin cell – vbat. If main power vdd fails and vbat is available. Is it possible still to count pulses from some pin low frekvecy counts like 10hz ? store to memory backup memory etc.

Leave a Reply

Your email address will not be published. Required fields are marked *