cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 RTC milliseconds setting

Tomohiro Shirane
Associate II
Posted on June 07, 2018 at 03:50

Hello,

I'm using the STM32 H753 Evaluation board, and trying to set the milliseconds by using HAL_RTC_SetTime function.

However, the HAL_RTC_SetTime function does not change the milliseconds(subseconds) value.

I've read the RTC synchronization chapter in the reference manual, but I don't understand it enough though.

If I would like to set the 400 milliseconds value, should I set the 0x190(= 400 decimal) into SUBFS field in RTC_SHIFTR and set the 0x3E7(= 999 decimal) into PREDIV_S field in RTC_PRER ?

Help would be appreciated.

Thanks.

Shirane.

9 REPLIES 9
Posted on June 07, 2018 at 09:08

Unless you want to use some nonstandard crystal, no.

The subsecond register runs in units given by the crystal and asynchronous part of divider (i.e. 1/(fLSE/(PREDIV_A+1)), which in the normal case is equal to 1 second/(PREDIV_S+1) ) and you should set the shift register in the same units.

In the default case, i.e. PREDIV_A = 0x007F, PREDIV_S = 0x00FF, to shift by 400ms you set SUBFS to 256*0.400≈102.

JW

Tomohiro Shirane
Associate II
Posted on June 13, 2018 at 12:16

Hello,

I've tried setting SUBFS field in SHIFT register but I did't get expeced result.

I've attached my code. The below is code snippet

--------------------------------------------------------------

[main.c] <- I've added the code that set SHIFTR after calling MX_RTC_Init();

/* Initialize all configured peripherals */

MX_GPIO_Init();

MX_USART2_UART_Init();

MX_RTC_Init();

/* USER CODE BEGIN 2 */

__HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);

hrtc.Instance->SHIFTR = 0x00000190;// 400msec

__HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);

/* USER CODE END 2 */

[rtc.c] <- set AsynchPredivas 31 andSynchPrediv as 999 in order to set the callendar clock into 1Hz.Currently I'm usingLSI(32KHz) as RTC clock.

void MX_RTC_Init(void)

{

RTC_TimeTypeDef sTime;

RTC_DateTypeDef sDate;

/**Initialize RTC Only

*/

hrtc.Instance = RTC;

hrtc.Init.HourFormat = RTC_HOURFORMAT_24;

hrtc.Init.AsynchPrediv = 31;

hrtc.Init.SynchPrediv = 999;

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(__FILE__, __LINE__);

}

/* USER CODE BEGIN RTC_Init 2 */

/* USER CODE END RTC_Init 2 */

/**Initialize RTC and set the Time and Date

*/

sTime.Hours = 0x13;

sTime.Minutes = 0x22;

sTime.Seconds = 0x30;

sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;

sTime.StoreOperation = RTC_STOREOPERATION_RESET;

if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

/* USER CODE BEGIN RTC_Init 3 */

--------------------------------------------------------------

My question is that:

  • Whereshould I add the code that sets SHIFTR ? Inside ofHAL_RTC_SetTime function ?
  • Is thereany code that I should call(add) around 'hrtc.Instance->SHIFTR ' ?

Thanks.

Shirane

________________

Attachments :

main.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HxVr&d=%2Fa%2F0X0000000az6%2FuL7ROgzBTPUFtaflQ8XCIP8fwLSVomvBhV.B9S88ZXg&asPdf=false

rtc.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HxVI&d=%2Fa%2F0X0000000ayx%2FtPf1npWlf4sv71iRsgEHSsyjggo0v5xurbKDNeLZu54&asPdf=false
Posted on June 13, 2018 at 12:47

I've tried setting SUBFS field in SHIFT register but I did't get expeced result.

What is the expected result and what was your observation?

JW

Posted on June 13, 2018 at 13:27

Hi,

MX_RTC_Init() sets the Hours as 0x13, Minutes as 0x22 and Seconds as 0x30.

And also, my code sets 400[msec] into 'hrtc.Instance->SHIFTR'.

In main.c, printf() is called on each 100[msec], that shows the current Hours, Minutes, Seconds and Sub-seconds.

>> printf('Hours = %d, Minutes = %d, Seconds = %d, SubSeconds = %d\n', time.Hours, time.Minutes, time.Seconds, msec);

So, the expected result are:

----------------------------------------------

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 400

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 500

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 600

........

----------------------------------------------

However, the current result are:

----------------------------------------------

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 0                   <-  SubSeconds starts with 0.

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 4294676       <-  Strange value ?

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 4294786      <-  Strange value ?

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 4294896      <-  Strange value ?

Hours = 13, Minutes = 22, Seconds = 30, SubSeconds = 39

----------------------------------------------

Thanks.

Shirane

Posted on June 13, 2018 at 13:36

>> printf('Hours = %d, Minutes = %d, Seconds = %d, SubSeconds = %d\n', time.Hours, time.Minutes, time.Seconds, msec);

msec is from where?

Read out and print the subseconds field before and after the shift.

JW

Posted on June 13, 2018 at 14:10

>> msec is from where ?

Please check the below code.

Setting SHIFTR is performed right after MX_RTC_Init( that calls HAL_RTC_SetTime inside it.)

And, after that, HAL_RTC_GetTime is called periodically(each 100msec) and prints current time field.

-------------------------------------------

  MX_RTC_Init();

  /* USER CODE BEGIN 2 */

  __HAL_RTC_WRITEPROTECTION_DISABLE(&hrtc);

  hrtc.Instance->SHIFTR = 0x00000190; // 400msec

  __HAL_RTC_WRITEPROTECTION_ENABLE(&hrtc);

  /* USER CODE END 2 */

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

   RTC_TimeTypeDef time;

   RTC_DateTypeDef date;

   HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);

   HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);

   uint32_t msec = 1000 * (time.SecondFraction - time.SubSeconds) / (time.SecondFraction + 1);

   printf('Hours = %d, Minutes = %d, Seconds = %d, SubSeconds = %d\n', time.Hours, time.Minutes, time.Seconds, msec);

   HAL_Delay(100);

  /* USER CODE END WHILE */

  /* USER CODE BEGIN 3 */

  }

-------------------------------------------

Posted on June 13, 2018 at 18:24

This is the note to description of the RTC_SSR register in RM:

Note: SS can be larger than PREDIV_S only after a shift operation. In that case, the correct

time/date is one second less than as indicated by RTC_TR/RTC_DR.

So, what happened was, that after MX_RTC_Init(), RTC_SSR == 999 as witnessed by the first printout (where thanks to the calculation formula it's printed as SubSeconds = 0). It takes some time until the correction is added from the shift register (see  RTC_ISR.SHPF), but if it would happen immediately the value of RTC_SSR would be 1399. After 100ms the value of RTC_SSR is 1299 and the formula calculates (999-1299)=0xFFFFFED4; 1000*0xFFFFFED4 = 0xFFFB6C20; 0xFFFB6C20/(999+1) = 4294667 -- you have SubSeconds = 4294676, the LSI does not tick exactly at 32kHz.

JW

Posted on June 16, 2018 at 02:05

Do you mean LSI should not be used as RTC clock ?

LSE is better than LSI ?

Posted on June 16, 2018 at 14:16

LSI is a very unprecise RC oscillator, there's no point in using it for timekeeping - its purpose is to provide a very rough wakeup source in applications, where the RTC does not need to keep real time.

JW