RTC (Real Time Clock) with calendar on STM32F3-Discovery board

In this article I will explain how to use RTC in STM32.

For this example I will use STM32F3-Discovery board with STM32F303VCT6, because it has USB port for serial data, so that we can get feedback.

We start as usual with new project in CubeMX. And we select STM32F303VC and click Start Project:

(I have all the microcontroller I have favourited, so that I don’t need to search for them each time)

We need a few peripherals:

  • DEBUG:
  • RCC:
  • USB (we need to enable it and select it’s class):
  • RTC:
  • LED Output:
    • first we need to set it as output (click on PE8 and select GPIO_Output:
    • and then we also need to label it (right click on PE8 and select Enter User Label and name it LED:

Now we go to Configuration tab and click on RTC:

Here we need to have Data format set as BCD (marked green).

And set time and date to let’s say current (marked blue).

And very important thing, we need to adjust the prescalers for clock, because default values are for 32768Hz clock but here we have 40kHz clock (marked red). One more important thing. If you do any changes in RTC registers and you don’t disconnect board from power, registers in RTC will remain even if board is reprogrammed!!! So for example if we change values for prescaler in CubeMX, regenerate, recompile and reprogram our microcontroller, the values in microcontroller won’t change until we disconnect power from board and reconnect it!

Now we go to Clock Configuration tab and it immediately suggests us to automaticly solve clock issues. We select Yes and it will do all for us:

Now we need to set project Settings…:

And enter project name and select our IDE:

Click Ok and generate code:

Once finished select Open Project, this will import project into SW4STM32:

Now inside SW4STM32 select Build:

You should get something like this at the end of compilation in Console window:

Now we need to program our microcontroller and connect it to computer to see if everything is ok so far. First programming. We need to right-click on project name and select Run As -> 1 Ac6 STM32…:

Once this finishes, we need to connect booth USB ports on discovery board to our computer. One is DEBUG/Power supply and second is Serial communication. Computer will install drivers for board and we should see new Serial Communication Device in Device Manager (I am using Windows):

This means that serial communication works. If you get error for device not recognized You probably have wrong clock configuration as I did for a while.

Now we can begin coding. As usually with LED blinking. We add two lines of code into main.c:

When we compile and program the Blue LED should blink with speed of 1Hz.

To be able to observe RTC we will use USB serial communication. For sending data out we use function called uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len). This function sends buffer *Buf of length Len through serial communication to our terminal program on PC. To be able to use it we need to include it’s header file:

If we look at beginning of main.c we can see hrtc variable define of type RTC_HandleTypeDef:

This variable takes care of our RTC and this is where we get our date and time from.

We will define three variables of our own (sTime1 for time, sDate1 for date and buffer for sending buffer:

To get time from RTC we use two functions inside main function HAL_RTC_GetTime and HAL_RTC_GetDate:

You need to use booth of these functions together or it won’t work!!! Quote from stm32f4xx_hal_rtc.c: “You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values in the higher-order calendar shadow registers to ensure consistency between the time and date values. Reading RTC current time locks the values in calendar shadow registers until current date is read.” End of quote!

With these functions we copy data from TRC registers to our two variables (sTime1 and sDate1).

The data is BCD coded so this means that for example 0x15 seconds means 15 seconds and not 21 seconds. So to get our data to buffer we need to do following:

  • we need to separate tenths and ones, we do this by for example, here let’s say that sDate1.Date = 0x12:
    • time[0] = sDate1.Date / 16;
      time[1] = sDate1.Date % 16;
  • now we have:
    • time[0] equals 0x01
    • time[1] equals 0x02
  • We cannot send this over serial communication because we are always sending ASCII values and so we need to send ASCII values of these numbers. ASCII value for number 0 is 48 or 0x30, for 1 is 49 or 0x31 etc. That is why we need to add these values to our current values. So proper function to get time into buffer for sending would be:
    • time[0] = (sDate1.Date / 16) + 48;
    • time[1] = (sDate1.Date % 16) + 48;

Now we can write code for sending data:

And when we program this code into microcontroler and start terminal we will get data like this:

One more thing. We need to be able to set clock. We do this using functions HAL_RTC_SetTime and HAL_RTC_SetDate. We do this by first writing values to two variables we are using sTime1 and sDate1 and then write to clock registers:

Here we are setting time and date to 10.10.2018 at 12 o’clock.


Thank you for reading!