Library 19- Use internal RTC on STM32F4

It’s been some time when I post last library. Next one is internal RTC library. STM32F4xx devices have Real Time Clock (RTC) inside, with support of internal calibrated 32768 Hz oscillator or external (more accurate) 32768 Hz oscillator.

RTC peripheral has also backup register support, which means that when you reset MCU, registers are not reset or if power is off and you have battery connected on Vbat pin, clock is still working.

RTC can also wakeup MCU from all powerdown modes. It has interrupt connected to EXTI lines which allows him to do that. As of version 1.1, you can now also wakeup MCU with alarm interrupt. This is now supported in library.

Library also provide converting time to epoch time (seconds from 01.01.1970 00:00:00) and back.

RTC peripheral has 2 between independent alarm sources which can trigger an interrupt once a week or once a month according to its settings. I have made a little explanation down, but you will see how to use it in example 2.

RTC Library

Features

  • Support Internal or external clock source
    • PC14 and PC15 pins are used for external crystal oscillator
    • STM32F4/429 Discovery does not have RTC crystal onboard. Check board’s manual on how to set it up
  • Support wakeup interrupt
  • Get seconds from 01.01.1970 00:00:00
  • Get readable time from seconds from 01.01.1970 00:00:00
  • Support to save/get data in binary or BCD format
  • Support for read/write data to/from RTC backup registers
  • Version 1.1 – October 20, 2014
    • Added support to set 2 internal alarms to trigger interrupts
    • They can also wake up STM32F4 from any low power mode
  • Version 1.2 – October 27, 2014
  • Version 1.4 – December 21, 2014
    • Added support to write data in string format,
    • Date&Time are checked before saved for valid input data
  • Version 1.5 – December 21, 2014
    • Added functions to get days in a month and days in a year
  • Version 1.7 – March 15, 2015
    • Added support for read/write from/to RTC backup registers

Dependencies

  • CMSIS
    • STM32F4xx
    • STM32F4xx RCC
    • STM32F4xx RTC
    • STM32F4xx PWR
    • STM32F4xx EXTI
    • MISC
  • TM
    • defines.h
    • attributes.h

Oscillator

STM32F4 has internal 32768 calibrated oscillator, which is not so calibrated as it is maybe heard. For any clock accuracy, you need external clock source. For this purpose, you can connect external 32768Hz crystal.

OSC 32768Hz STM32F4xx Description
OSC1 PC14 Oscillator pin 1
OSC2 PC15 Oscillator pin 2

Datetime structure

Time structure is used to work with time.

Datetime format structure

These are options which you use when set or get data from RTC.

Clock source structure

RTC can work with internal or external oscillator.

Remember: Internal RC oscillator (it says that is calibrated) is not accurate at all. It failed about 2 seconds per minute on my both discovery boards. Use external clock source.

Interrupt structure

Wakeup with RTC is also possible. Below is structure where you can set every x seconds interrupt will happen.

Initialize RTC peripheral

On power on, you have to initialize RTC peripheral. This function enables clock for RTC, synchronize registers and prepare RTC to work.

Set date and time

RTC is set to 01.01.01 00:00:00 on power up, if it is not configured before. If time is configured and reset happen, time should stay as it was before reset.

To set data, you have to fill time structure. When you do this, use

Get date and time

To get data from RTC you also need to have initialized time struct. Then use it like when you set date and time.

Seconds from 01.01.1970 00:00:00

I also made a function which calculates seconds from 01.01.1970 00:00:00.

Note: When you call function to get time from RTC, this function is also used to calculate time and store it in unix member of time structure.

Get date and time from 01.01.1970 00:00:00

Let’s say, that you are working on project where you have to save your time somehow. If you save date, month, year… separatelly, this will take a lot of bytes. If you convert time to seconds offset from 01.01.1970 00:00:00, and save it, that takes 4bytes, which is smaller. But than you have to get time back from this seconds. This is doing function below. It converts seconds from 1970 to a human readable time.

RTC wake up interrupt

Because RTC support wakeup interrupt, you can use it if you need it. For that purpose, I wrote a function. As parameter you have to pass it Interrupt time struct

Also, when you activate wakeup interrupt, if you want to handle it, you have to make another function somewhere in your project (let’s say in main.c)

RTC Alarms

RTC peripheral on STM32F4 has capability to trigger 2 different alarms, Alarm A and Alarm B. They can be set, to trigger interrupt one time in a week or one time in a month. Also, they are completely independent between each, but they have interrupt handler in common. You are of course able to set one alarm to be triggered each month and one to be triggered each week.

RTC subsecond

RTC in STM32F4 supports also subsecond accuracy. But here is one problem. Subsecond depends on values you set for your “prescaler”. STM32F4’s RTC has 2 predivision values:

  • ASYNC: 7-bit asynchronous prescaler
    • Max value can be 0x7F
  • SYNC: 15-bit synchronous prescaler
    • Max value can be 0x7FFF

These 2 values are used to “digital” fix inaccuracy for RTC. Equation for RTC 1Hz clock is:

rtc_1hz_clock = RTC_IN_CLK(LSI or LSE) / ((ASYNC + 1) * (SYNC + 1))

By changing these two values, you can set your custom prescaler for RTC, but result should always be one.

You are maybe asking, why I’m posting this in subsecond section. The point is also, that subsecond “resolution” depends on SYNC value. Bigger than this value is, better resolution you will get for subsecond, max of max SYNC value. Subsecond is a downcounter. When it reaches zero (0), seconds are updated and it’s reload value is the same as SYNC value. For that purpose I’ve also edit this two constants:

  • Before
    • ASYNC: 0x7F
    • SYNC: 0x00FF
  • Now
    • ASYNC: 0x1F
    • SYNC: 0x03FF

This give us now 1/1024 of a second resolution. Subseconds are read from RTC registers when you read clock. I have also made some modification to library, which now allows you to custom set values for ASYNC and SYNC. If you need to calibrate your RTC crystal, you can set them to match your crystal frequency.

To get proper milliseconds from last second, you can do some easy math:

  • General
    • milliseconds = 1000ms – (subseconds * 1000 / SYNC)
  • Our case
    • milliseconds = 1000ms – (subseconds * 1000 / 1023)
  • Subsecond register is downcounter, but we probably want milliseconds to raise with time, so 1000ms – is at the beginning of equation

Open defines.h file and edit settings:

  • When you set this new library, you have to set date and time again, or your settings will not be valid!
  • You can not set subseconds, you can just read it
    • When you update your clock, subsecond is set to reload value = SYNC value

Set date and time with string

Sometimes, useful function will be to set date and time using string format. For that purpose (in version 1.4) I’ve added this option. Function accepts pointer to string in format below:

Example 4 shows you how to use this.

RTC backup registers

RTC features 20 internal backup registers where you can store anything and will be available whole time RTC is active and has power.

My library uses backup register 19 (last one) to store informations about library, so you are not allowed to store data there. This is also prevent using my functions for that.

I’ve made 2 functions for this.

Look at example 5 how to use this.

Functions and enumerations

Below are listed all functions and enumerations used in this library. In new version 1.1, alarm is supported. How to properly use it, look at example 2.

Common questions

Why is RTC not updated on read?

When i developed this library, I found somekind of a bug on STM32F4 RTC peripheral. If I first read date register and then time register, date was not correct updated on read. If I turn this arround, so first time, then date, everything was perfect.

Example 1

  • Wakeup interrupt is triggered each second.
  • After trigger, date & time is read from MCU and displayed over USART3 to user.
  • If you press button on discovery boards, date & time is set to some other value.

Example 2

  • Example below works the same as Example 1, except Alarms A and B are activated
  • If you press the button, global date & time is set to 21:11:00
    • Alarm A is triggered each week at day 1 (Monday is day 1, Sunday is day 7) at time 21:11:05
      • After 5 seconds Alarm A is first time triggered
    • Alarm B is triggered each month at day 20 at time 21:11:10
      • After 10 seconds Alarm B is first time triggered

RTC Alarms A and B triggered

RTC Alarms A and B triggered


Example 3

  • Example below works the same as example 1, just subsecond is added to USART output.
  • Wakeup interrupt is set to 125ms, so you can see counter
  • Important
    • Subsecond register is downcounter, so do not be confused

Example 4

  • USART1 (TX: PB6, RX: PB7, 115200baud) waits for any string (with \n at the end),
  • received string is then analyzed with RTC internal checker,
  • if date and time are valid, RTC is set
  • For example, send from your USART:
    • 11.12.14.4;10:45:50\n
    • Date: 11
    • Month: 12
    • Year: 2014
    • Day in a week: 4 (Thursday)
    • Hours: 10
    • Minutes: 45
    • Seconds: 45

Example 5

  • If RTC is first time initialized, data is store to RTC backup register 4
  • If you press button on discovery/nucleo board, board will reset
  • After reset, RTC is still initialized and you will be able to test if written data is the same as read

Projects are available at Github, download library below.

Icon
TM STM32F4 RTC Library

Internal RTC on STM32F4xx

tilz0R

Owner of this site. Also electronic enthusiasts, web developer, 3D printer fan, handball player and more. Big fan of STM32F4 devices. In anticipation of the new Discovery board for STM32F7 lines.

You may also like...

Read before commenting!

Before you make a new comment, make sure you agree with things listed below:

  • - Read post to make sure if it is already posted what you are asking for,
  • - Make sure you have the latest version of libraries used in your project,
  • - Make a clean and grammatically correct written message,
  • - Report as many details as possible, including what have you done so far,
  • - Do NOT post any code here. Use Pastebin,
  • - Do NOT post any error codes here. Use Pastebin,
  • - Specify STM32Fxxx family and used Discovery/EVAL/Nucleo or custom made board,
  • - Make sure your clock is set correct for PLL,
  • - If you are using my HAL drivers, please check this post how to start.
Comment will be deleted on breaking these rules without notification!
  • Yannis

    Hello !
    Thank you for everything you do, that’s really useful.
    Here’s my question, I’m trying to use the internal clock to display the time on a LCD. The thing is, every minute takes 71 seconds instead of 60. I searched in the code but I couldn’t find anything.
    Is there a way to compensate that ? Like setting the flag at 48 seconds ?
    Thank you for your response.

    PS: I’d rather only use the internal clock.

    • Wow..71seconds?
      That’s weird. Can you show me your usage code?

      • Yannis

        Okay, I tried to summarize my program with only the time part.

        void main(void)
        {
        /* Unlock the Flash Program Erase controller */
        FLASH_Unlock();

        /* EEPROM Init */
        EE_Init();

        systickInit(1000);
        SystemInit();

        //Initialize RTC with internal 32768Hz clock
        //It’s not very accurate
        if (!TM_RTC_Init(TM_RTC_ClockSource_Internal))

        {
        //Set wakeup interrupt every 1 second
        TM_RTC_Interrupts(TM_RTC_Int_1s);

        datatime.hours = 11;
        datatime.minutes = 00;
        datatime.seconds = 00;
        datatime.year = 14;
        datatime.month = 10;
        datatime.date = 1;
        datatime.day = 4;

        //Set new time
        TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
        }

        RTC_GetTime(RTC_Format_BIN, &clock1); //clock1 is a RTC_TimeTypeDef

        // this part is used to put time in a string (##:##)
        sprintf(strClock,”%d:%dn”,clock1.RTC_Hours,clock1.RTC_Minutes);

        WriteGeorgiaStrS(strClock,250,8,White); // displays on the LCD

        while(1)
        {
        RTC_GetTime(RTC_Format_BIN, &clock2); //clock2 is a RTC_TimeTypeDef

        if(clock1.RTC_Minutes == clock2.RTC_Minutes);
        else
        {
        //when clock2 changes: Hide the previous time displayed and put the new one
        RTC_GetTime(RTC_Format_BIN, &clock1);
        LCD_DrawFullRect(250, 8, 80, 20, Blue);
        sprintf(strClock,”%d:%dn”,clock1.RTC_Hours,clock1.RTC_Minutes);
        WriteGeorgiaStrS(strClock,250,8,White);
        }
        }
        }

        • You use my library for initialize and then custom for read data. Try to read data with my lib

          • Yannis

            Okay I changed my code into this, but it does the same curious thing.

            void main(void)
            {
            /* Unlock the Flash Program Erase controller */
            FLASH_Unlock();

            /* EEPROM Init */
            EE_Init();

            systickInit(1000);
            SystemInit();

            //Initialize RTC with internal 32768Hz clock
            //It’s not very accurate
            if (!TM_RTC_Init(TM_RTC_ClockSource_Internal)) {
            //Set wakeup interrupt every 1 second
            TM_RTC_Interrupts(TM_RTC_Int_1s);

            datatime.hours = 11;
            datatime.minutes = 00;
            datatime.seconds = 00;
            datatime.year = 14;
            datatime.month = 10;
            datatime.date = 1;
            datatime.day = 4;

            //Set new time
            TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
            }

            TM_RTC_GetDateTime(&clock1, RTC_Format_BIN);
            //clock1 & clock2: TM_RTC_Time_t type

            // this part is used to put time in a string (##:##)
            sprintf(strClock,”%d:%dn”,clock1.hours,clock1.minutes);

            WriteGeorgiaStrS(strClock,250,8,White); // displays on the LCD

            while(1)
            {
            TM_RTC_GetDateTime(&clock2, RTC_Format_BIN);

            if(clock2.minutes == clock1.minutes);
            else
            {
            TM_RTC_GetDateTime(&clock1, RTC_Format_BIN);
            LCD_DrawFullRect(250, 8, 80, 20, Blue);
            sprintf(strClock,”%d:%dn”,clock1.hours,clock1.minutes);
            WriteGeorgiaStrS(strClock,250,8,White);
            }
            }
            }

  • Miguel Moreto

    Hello Majerle,

    thank you so much for these libs! they are great and very well coded! Congratulations!

    I would like to inform you that this lib is working very well with my ST NucleoF401 board. The board have an external clock.

    I use Cocoox CoIDE with ARM GCC. The only thing I had to modify is the definition of the __weak atribute to functions.

    I just added to my defines.h:

    #define __weak __attribute__ ((weak))

    I belive this related with diferences between ARM GCC and the Keil compiler.

    Best regards!

    Miguel
    Florianopolis – Brazil

  • dd

    mm

  • dd

    There is a bug in TM_RTC_GetDateTimeFromUnix() for leap years when date is 31th December.
    while (1) {
    if (TM_RTC_LEAP_YEAR(year) && (epoch >= 366)){
    epoch -= 366;
    } else if (epoch >= 365) {
    epoch -= 365;
    } else {
    break;
    }

    year++;
    }

    should be changed to:

    /* Bug removed */
    while (1) {
    if (TM_RTC_LEAP_YEAR(year)){
    if(epoch >= 366) {
    epoch -= 366;
    }else{
    break;
    }
    } else if (epoch >= 365) {
    epoch -= 365;
    } else {
    break;
    }
    year++;
    }

    • Nice for posting this.
      Probably could be, but I didn’t see on any test this.

      Will fix that.

  • BK

    Hi friend,I wanna ask you something,For example,I am arranging my time,ok,everyhing is good,But,When I cut electricity,I have to arrange again everything.How can update time automatically.Thanks…

  • محــمد مهــدی سلطانی

    Hi friend
    I have an Unknown problem!
    when I use the Delayms() function in one of the RTC ALAM Handlers, it doesn’t works!!!
    May you help me?

    • For delay, interrupt is used, for alarm interrupt is used.
      When you are in ine interrupt you cant expect another one.

      Also, having delay in interrupt routine is very bad idea.

      • محــمد مهــدی سلطانی

        Thanks so much…

  • jd

    Hi all.

    i have problem

    i connected the super-cap to VBAT pin.
    but not running rtc timer during power off time
    I made sure that the super capacitor voltage is 2.65V
    and then external osc clock out

    at next power on time, the rtc time is last power off time.

    It seems not running rtc while power off time

    i had test at LSE and LSI.

    My STM- board has an external rtc clock

    Here is my main function

    int main(void)
    {
    RNG_Config();

    //168MHz Over Clock
    if(SysTick_Config(SystemCoreClock / 2000))
    {
    /* Capture error */
    while (1);
    }

    if (!TM_RTC_Init(TM_RTC_ClockSource_Internal)) {
    //if (!TM_RTC_Init(TM_RTC_ClockSource_External)) {

    TM_RTC_Time_t datatime;

    datatime.hours = 0;
    datatime.minutes = 0;
    datatime.seconds = 0;
    datatime.year = 15;
    datatime.month = 1;
    datatime.date = 1;
    datatime.day = 4;

    TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
    }

    TM_RTC_Interrupts(TM_RTC_Int_1s);

    while(1)

    {

    }

    }

    void TM_RTC_RequestHandler() {

    Gettime(USART1);

    }

    • Try with real and stable 3V3 on Vbat pin.
      Also, enable external clock again.

      It just MUST work, worked on all my boards for STM32F4.

  • Petr Machala

    Hi,

    Can I have a question about RTC_Init function? The input parameter is the source of the clock (internall or external) and then there is a IF function for RTC_STATUS_TIME_OK, RTC_STATUS_INIT_OK and first init…the inicialization of the clock source is done by function RTC_Config…I dont get why internal clock is inicialized every time but externall clock only for first init…shouldnt there be asomething like this?

    if (source == RTC_AWU_ClockSource_Internal) {
    RTC_AWU_Config(RTC_AWU_ClockSource_Internal);
    } else{
    RTC_AWU_Config(RTC_AWU_ClockSource_External);
    }

    • You are not using my lib, so I have idea what are you talking about 😉

      • Petr Machala

        I renamed the functions otherwise it is unchanged…I have fix it above…

        • I like sharing my work with others, but I also expect than you leave function names as they are.
          I really don’t approve the thing like you do in your work.

          So I won’t answer your question. Sorry.

  • Himanshu

    hi, i tried you rtc code it work very well till power is on. Once power is lost it starts from the time power is switched off. plz suggest. I checked battery is connected to VBAT and giving stable supply.

    • Hi,

      the RTC should work in power off with only VBAT pin too.
      Do you have any discovery/nucleo board?

      VBAT pin is there connected directly to VCC so if no VCC, then no VBAT.
      Check boards manual for jumpers you have to set/remove to get VBAT to be connected to your external power.

  • George

    Hi,

    Thanks for the libraries. The help a lot. I’m new at using an RTC. Can you please tell me why my external clock source isn’t working if I initialized it. I connected a 32.768kHz crystal to PC14 and PC15 and nothing is happening. As soon as I change to internal then it works fine

    • Hi.
      Make sure you have capacitors added also.
      Make sure that crystal oscillates.

      Tested on my several boards and custom boards and it works ok.

      • George

        I added capacitors. One end to the pin and the other to ground. I did this for both pins. Is therer any other code i should add? Do I still use the TM_RTC_RequestHandler ()? Because I am using it.

        • Yes, you can use it but not necessary.

          • George

            I cant seem to get the external clock to work

          • There should be hardware problem.

            I got this library working on several boards, nevem any problems, so I expect that library works OK. Please research your hardware.

  • Pingback: Library 15- DS1307 Real Time Clock for STM32F4 - STM32F4 Discovery()

  • Pingback: HAL Library 24- RTC for STM32Fxxx - STM32F4 Discovery()

  • Mohammad Kamel

    hello ! i have a question i need every 2ms interrupt what should i do for solving this problem thanks alot

    • 1. Use systick with 1ms interrupt and do task every second interrupt.
      2. Use one of many timers for that purpose

      I prefer option 1.

      • Mohammad Kamel

        thanks alot

  • manju nath

    Thank you so much to Majerle Tilen.
    I have some query about alarms A & B.
    Can set 10 different timings to alarm A & B.?
    Is there any snooze option available by on stm32F429Zi.

    If yes.Then how can I set 10 alarms and snooze options?

    • Only one active time at a time 😉
      If you need 10 alarms, then save other times somewhere. When first alarm occurs, set new time from saved list.

  • manju nath

    Majerle sir, please give me some hints on How to use backup registers(0 to 18), I mean how to write rtc_sting like “03.09.15.4;11:45:50” into backup register.Then how to read it and set rtc clock.

    • Your time string needs 19 bytes of memory. To save memory, convert your time to unix timestamp (seconds from 1.1.1970) and 4-bytes of memory will be enough. Then use my function to write rtc backup register and do it!

      • manju nath

        Majerle sir, even though can I store Alarm time into back registers.If yes. then how can I
        store alarm time into backup registers? is there any way…
        Is it possible to convert alarm time to unix time.? please give me hints sir.

  • kyb

    Why do you reconfigure RTC clock source, if it is set to internal, while RTC is already configured and works? File tm_stm32_rtc.c at lines 86-87.
    http://pastebin.com/sGLRDFC4#

    • I know,

      for some reason (some time, not always), RTC didn’t worked after board restart if internal crystal was used. So I reiniti it again and then always worked.

  • kyb

    Have U read what says Ref.Man about how to determine if the calendar has been initialized?
    > After a system reset, the application can read the INITS flag in the RTC_ISR register to check if the calendar has been initialized or not. If this flag equals 0, the calendar has not been initialized since the year field is set at its backup domain reset default value (0x00).

    Why do you use BKPxR?

  • Christian Julius

    Hi,
    any idea how to substract some pulses if the clock is too fast, 1s per day? I dont use your lib because I found that the StdPeriph Lib is enough and good for understanding, but some things are unclear. To substract some pulses, what is the correct parameter string for this function?

    * @brief Configures the Smooth Calibration Settings.
    * @param RTC_SmoothCalibPeriod : Select the Smooth Calibration Period.
    * This parameter can be can be one of the following values:
    * @arg RTC_SmoothCalibPeriod_32sec : The smooth calibration period is 32s.
    * @arg RTC_SmoothCalibPeriod_16sec : The smooth calibration period is 16s.
    * @arg RTC_SmoothCalibPeriod_8sec : The smooth calibration period is 8s.
    * @param RTC_SmoothCalibPlusPulses : Select to Set or reset the CALP bit.
    * This parameter can be one of the following values:
    * @arg RTC_SmoothCalibPlusPulses_Set : Add one RTCCLK pulse every 2**11 pulses.
    * @arg RTC_SmoothCalibPlusPulses_Reset: No RTCCLK pulses are added.
    * @param RTC_SmouthCalibMinusPulsesValue: Select the value of CALM[8:0] bits.
    * This parameter can be one any value from 0 to 0x000001FF.

  • Mustafa

    Hi, Firstly, thank you so much for your sharing. This library does not work with external clock or there is a bug. I checked all signal with scope, 32.768 bring stm32F429I’s pins but does not work. When i use internal clock system is work and after reset system resume. I designed a bord so i work on my board.

    Best..

    • Hi. Exactly this lib isused on my several project with external clock, so first nake sure your oscillator works and is connected on right pins.

      • Mustafa

        I changed only TM_RTC_Init function parameter as a TM_RTC_ClockSource_External on your software. Is it enough?
        TM_RTC_Init(TM_RTC_ClockSource_External);

        • Yep. Another is hardware.

          • Mustafa

            How do i find this problem. Do you have any suggest.

          • Already told you.

          • Mustafa

            Hi Majerle,

            I configured MCO pin (PA8) and ı saw square wave on the Scope. Can i say that 32.768Khz osc connected correct pins and it is working.

            Best

          • What is working and what not?

          • Mustafa

            Hi, Firstly, thank you so much for your sharing. This library does not work with external clock or there is a bug. I checked all signal with scope, 32.768 bring stm32F429I’s pins but does not work. When i use internal clock system is work and after reset system resume. I designed a bord so i work on my board.

            Best..

          • Looks like you are pretty confident you did everything OK with hardware.
            Waiting for your fix. Will be glad to merge it.

          • Mustafa

            Hi, I found this from,

            https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy%2est%2ecom%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fUnable%20to%20Set%20RTC%20on%20STM32F4&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=1005

            void RTC_Configuration(void)

            {

            #define FIRST_DATA 0x32F2

            uint32_t val = 0;

            RTC_InitTypeDef RTC_InitStructure;

            RTC_TimeTypeDef RTC_TimeStructure;

            RTC_DateTypeDef RTC_DateStructure;

            uint32_t uwSynchPrediv, uwAsynchPrediv;

            /* Enable the PWR clock */

            RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

            /* Allow access to RTC */

            PWR_BackupAccessCmd(ENABLE);

            /* Enable the LSE OSC */

            RCC_LSEConfig(RCC_LSE_ON);

            /* Wait till LSE is ready */

            while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

            {

            }

            /* Allow access to RTC */

            PWR_BackupAccessCmd(ENABLE);

            /* Select the LSE as RTC Clock Source */

            RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

            /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/

            uwSynchPrediv = 0xFF;

            uwAsynchPrediv = 0x7F;

            /* Enable the RTC Clock */

            RCC_RTCCLKCmd(ENABLE);

            /* Wait for RTC APB registers synchronisation */

            RTC_WaitForSynchro();

            // Write to the first RTC Backup Data Register

            RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);

            // Set the Time

            RTC_TimeStructure.RTC_Hours = 0x08;

            RTC_TimeStructure.RTC_Minutes = 0x00;

            RTC_TimeStructure.RTC_Seconds = 0x00;

            // Set the Date

            RTC_DateStructure.RTC_Month = RTC_Month_July;

            RTC_DateStructure.RTC_Date = 0x27;

            RTC_DateStructure.RTC_Year = 0x14;

            RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Monday;

            // Calendar Configuration

            RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;

            RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;

            RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

            RTC_Init(&RTC_InitStructure);

            // Set Current Time and Date

            RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);

            RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);

            val = (uint32_t)RCC->BDCR;

            if (val & 0x1)

            LCD_DisplayStringLine(LINE(0), (uint8_t *)”LSE On”); //printf(“LSE Onn”);

            else

            LCD_DisplayStringLine(LINE(0), (uint8_t *)”LSE Off”); // printf(“LSE Offn”);

            if (val & 0x2)

            LCD_DisplayStringLine(LINE(1), (uint8_t *)”LSE Ready”);//printf(“LSE Readyn”);

            else

            LCD_DisplayStringLine(LINE(1), (uint8_t *)”LSE Not Ready”);//printf(“LSE Not Readyn”);

            if (val & 0x4)

            LCD_DisplayStringLine(LINE(2), (uint8_t *)”LSE ByPass On”);//printf(“LSE ByPass Onn”);

            else

            LCD_DisplayStringLine(LINE(2), (uint8_t *)”LSE ByPass Off”);//printf(“LSE ByPass Offn”);

            if (val & 0x8000)

            LCD_DisplayStringLine(LINE(3), (uint8_t *)”RTC Clock Enabled”);//printf(“RTC Clock Enabledn”);

            else

            LCD_DisplayStringLine(LINE(3), (uint8_t *)”RTC Clock Disabled”);//printf(“RTC Clock Disabledn”);

            switch(val & 0x300) {

            case 0x100 : LCD_DisplayStringLine(LINE(4), (uint8_t *)”RTC Clock Source LSE”); break; // puts(“RTC Clock Source LSE”); break;

            case 0x200 : LCD_DisplayStringLine(LINE(4), (uint8_t *)”RTC Clock Source LSI”); break; // puts(“RTC Clock Source LSI”); break;

            case 0x300 : LCD_DisplayStringLine(LINE(4), (uint8_t *)”RTC Clock Source HSE/%d”); break;//printf(“RTC Clock Source HSE/%d”, (RCC->CFGR >> 16) & 0x1F); break;

            default : LCD_DisplayStringLine(LINE(4), (uint8_t *)”RTC Clock Unknown”);

            }

            }

            I got,

            LSE On

            LSE Ready

            LSE ByPass Off

            RTC Clock Enabled

            RTC Clock Source LSI -> I’m going to freak out :-). Why i got LSI still ? I also already got square wave on PA8

          • Mustafa

            Hi, I found problem. There is a bug.

            When I put “RTC_WriteProtectionCmd(DISABLE);” funtion before call RTC_WaitForSynchro() function RTC got the work on.

            The RTC Resynchronization mode is write protected, use the TC_WriteProtectionCmd(DISABLE) before calling this function.

            Best.

          • Happy to fix it.

          • Mustafa

            Yes bro you are right. However, not only your example but also other examples in the internet same which is not include RTC_WriteProtectionCmd(DISABLE); function.

            But I realize that there is a note altought include this code

            RTC->WPR = 0xCA;
            RTC->WPR = 0x53;

            * @note The RTC Resynchronization mode is write protected, use the
            * RTC_WriteProtectionCmd(DISABLE) before calling this function.
            ErrorStatus RTC_WaitForSynchro(void) {
            ..
            ..
            }
            thank you for your understanding

  • Davit Hakobyan

    The line RTC_BCD2BIN(x) ((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))

    should not be like:

    RTC_BCD2BIN(x) ((((x) >> 4) & 0x0F) * 16 + ((x) & 0x0F))
    i.e. x10 to be changed to x16?

    • Hi Davit,

      you are wrong here. Number is in BCD format and to transfer it to BINARY, we use formula as first one.

      Simple example. Let’s say we have a 8 bit number 76.
      In binary, this would be: 0b 0100 1100

      In BCD, this would be: 0b 0111 0110 because each 4 bits have one digit, in your case MSB 4 (upper nibble) bits: 0111 = 7 and lower (lower nibble): 0110 = 6.

      So, to go from BCD to BIN, we have to do this: (10 * upper nibble) + lower nibble = 10 * “0111” + 0110 = 10 * 7 + 6 = 76.

      Hope you understand.

      • Davit Hakobyan

        Hi Tilen,
        Thanks a lot for prompt clarification.

  • Jay Katira

    Hi Tilen Majerle, I used this library, it works very well, thank you for that. I have a query that if i power off the board. and giving 3.3 v DC using battery for VBAT pin, but its not updating RTC time. Any suggestion?

    • If you first power off, then put 3V to VBAT pin then it sure won’t work because RTC registers get reset when you completelly power off.

      Use external clock source as well.

      • Jay Katira

        I have connected it before power off the board.

        • And you didn’t said about external clock.

          • Jay Katira

            Sorry Sir, I am not using external clock, i just want to use Internal RTC clock. if possible. I want to know that IS it not working well when we use internal clock source? Actually I wanted to do that if i can use internal clock source and RTC working then My SPI pins can be used for other purpose.

          • Sounds like you still need main power.

          • Jay Katira

            The purpose is that when electricity wont work then also my RTC should work. and If its possible to use Internal RTC then its little beneficial to me. I want your suggestion for this. Can we update the Internal RTC when we don’t have Power, Condition accepted that 3 v is given to VBAT pin before Power off?

          • Clock will fail for sure.

          • Jay Katira

            Okey, then i have to Use External Crystal for that right?

          • Jay Katira

            One more query that Data sheet says that if we give 3 v to VBAT pin then it will keep on internal RTC and Backup registers.

          • Jay Katira

            Is it possible we write this clock data to other register and every initialize time we read it from that other register? Is it work?

  • Mat

    Hi Tilen,
    I have question according to Your code.
    I have problem because I would like to do something like that:

    ….. time
    time=TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);

    printf(buf,%d:%d:%d,time.hours,time.minutes,time.seconds)
    TM_HD44780_Puts(0, 1, time)

    What is the type of my variable time ?

    • You can’t do it that way.

      • Mat

        So what can You recommended ?

        • As I see, you don’t know anything else, except this syntax:
          myvariable = myfunctionWithReturnData();

          In C, not everything goes this way. You have clear example on how to read data which is saved to structure you pass as parameter to function. Use it!

          As I remember, you wanted the same on DS18B20 today. I will say it again. Both function (DS and RTC here) returns status if they were successful or not, while data when they are succedded are stored into variables which are passed as pointers to functions.

          End of discussion!

  • Abhinav Kumar

    Hi Tilen,

    I configured the STM32 board RTC with the LSI clock.
    What i am observing is that there is a time lag of 17 min in 24 hours.
    Can you please suggest how to calibrate the RTC so as to avoid the time lag.

    Thanks in advance.

    • 1. use LSE
      2. use RTC SYNC and ASYNC values to calibrate.

  • Qfnnn

    Hi TM:

    I am using the function of wakeup MCU every X second. (TM_RTC_Interrupt)

    I notice that 60 second (0x3BFFF) and 30 second (0x1DFFF) don’t work in the desired way. Then I check the function RTC_SetWakeUpCounter in stm32f4xx_rtc.c and find out that the parameter of this function is only available from 0x0000 to 0xFFFF.

    So 60s (0x3BFFF) and 30s (0x1DFFF) are unavailable to be set and I report this to you.

  • Nguyễn Phúc Anh Đồng

    Everything works fine but I can’t see anything appear on Hercules Terminal, I connect PB10 of STM32f4 to RX pin of my USB UART, and PB11 to TX pin of the USB UART but nothing happened. Please help me why? Thansk

  • vanaja

    Hi,

    I need alarm event for every 3hrs. is it possible.

  • Marek

    Hey Man, you have helped me a lot with this code. I really appreciate! Thanks a lot!

  • RusikOk

    how to check the clock to our initialization of the battery or not? so as not to expose them at every turn it on