cancel
Showing results for 
Search instead for 
Did you mean: 

RTC Issue

CBerg
Senior II

Hello Community!

I have an issue with reading / writing the RTC in an H723 MCU.

The issue is:

I can set the Clock to a date, but when I read out the RTC, then the year is 10 years in the future.

e.g. I set the time to now (2025 / 06 / 22 19:mm:ss) and I read out the RTC after that, i get the corret day of month, month, hour, minute and second but the yearis 2035 (or better: 35 instead of 25, because the year in the Date Typedef is an u8 integer). This is my code:

 

	RTC_DateTypeDef d;
	RTC_TimeTypeDef t;

	d.Year = (uint8_t)(hDateTime->dt.year - 2000);
	d.Month = hDateTime->dt.month;
	d.Date = hDateTime->dt.day;
	t.Hours = hDateTime->tm.hour;
	t.Minutes = hDateTime->tm.min;
	t.Seconds = hDateTime->tm.sec;
	if(hDateTime->tm.dst) {
		t.DayLightSaving = RTC_DAYLIGHTSAVING_ADD1H;
	} else {
		t.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
	}

	uint8_t retval = 0;
	if(HAL_OK != (HAL_RTC_SetTime(&hrtc, &t, RTC_FORMAT_BIN))) retval |= 2;
	if(HAL_OK != (HAL_RTC_SetDate(&hrtc, &d, RTC_FORMAT_BIN))) retval |= 1;

	if(HAL_OK != (HAL_RTC_GetDate(&hrtc, &d, RTC_FORMAT_BIN))) retval |= 4;
	if(HAL_OK != (HAL_RTC_GetTime(&hrtc, &t, RTC_FORMAT_BIN))) retval |= 8;

Has anyone an idea, what's going wrong here? IMHO this is pretty straight forward and I don't know where the 10 years come from. I send the year information to this function as e.g. 2025, I subtract 2000 to make an u8 from it and push that into the RTC. Why does it add 10 years?

Thanks and cheers!

1 ACCEPTED SOLUTION

Accepted Solutions

Thanks for your input, @Saket_Om 

the issue is resolved. The mistake was, that I did not initialize the variables I used for setting the Clock to Zero.

 

View solution in original post

4 REPLIES 4
AScha.3
Super User

Hi,

read rm.

afair ... always read time first , then date !

 

+ i didnt understand, what HAL is doing, so i just read it from registers:

void show_time()
{
	uint32_t rTR = RTC->TR;											// read time register first !
	uint32_t rDR = RTC->DR;											// read date register

	Time.Hours   = (uint8_t)((rTR & 0x300000)>>20)*10 + ((rTR & 0xF0000)>>16);	// BCD -> "normal"-format
	Time.Minutes = (uint8_t)((rTR & 0xF000)>>12)*10 + ((rTR & 0x0F00)>>8) ;
	Time.Seconds = (uint8_t)((rTR & 0x0070)>>4)*10 + ((rTR & 0x000F)) ;
	Date.Year    = (uint8_t)((rDR & 0xF00000)>>20)*10 + ((rDR & 0xF0000)>>16) ;
	Date.Month   = (uint8_t)((rDR & 0x1000)>>12)*10 + ((rDR & 0x0F00)>>8) ;
	Date.Date    = (uint8_t)((rDR & 0x0030)>>4)*10 + ((rDR & 0x00F)) ;


	sprintf(TempChar,"%d/%d %02d:%02d:%02d ",  Date.Month, Date.Date, Time.Hours, Time.Minutes, Time.Seconds);
	ST7789_WriteString(0, 4,TempChar, Font_7x10, WHITE,  0); // show on screen

}
If you feel a post has answered your question, please click "Accept as Solution".
CBerg
Senior II

Yes, I read the RM, but that did not help me - this is why I was asking here.

The HAL functions do pretty much the same, you do in the code you posted.
They convert the u8 values into the BCD format and set the registers - as you do above - or BCD to binary.

inside the HAL_RTC_set_date the code for "BINARY" is as follows:

  if(Format == RTC_FORMAT_BIN)
  {
    assert_param(IS_RTC_YEAR(sDate->Year));
    assert_param(IS_RTC_MONTH(sDate->Month));
    assert_param(IS_RTC_DATE(sDate->Date));

    datetmpreg = (((uint32_t)RTC_ByteToBcd2(sDate->Year)  << RTC_DR_YU_Pos) | \
                  ((uint32_t)RTC_ByteToBcd2(sDate->Month) << RTC_DR_MU_Pos) | \
                  ((uint32_t)RTC_ByteToBcd2(sDate->Date)  << RTC_DR_DU_Pos) | \
                  ((uint32_t)sDate->WeekDay               << RTC_DR_WDU_Pos));
  }

and RCT_ByteToBcd2 splits the binary value and converts it into BCD format:

uint8_t RTC_ByteToBcd2(uint8_t Value)
{
  uint32_t bcdhigh = 0U;
  uint8_t  bcdlow  = Value;

  while (bcdlow >= 10U)
  {
    bcdhigh++;
    bcdlow -= 10U;
  }

  return ((uint8_t)(bcdhigh << 4U) | bcdlow);
}

Note: both functions are auto-generated by CubeMX.

so when I set the year to 2025, i subtract 2000, then the binary value for year is 25. 25 is sent into "ByteToBCD", which results in "2" for the HIGH byte (RTC_DR bit 20..23) and 5 for the LOW byte (RTC_DR bit 16..19). Or the other way round: if I set the date (after the time) to todays date 2025/06/23 the RTC_DR Register is set to

0b0011 0101 1000 0110 0010 0011 (leading 0 removed)

This means:

RTC_DR:DU[0..3] = 0b0011 = 3
RTC_DR_DT[4..5] = 0b10 = 2

=> day of month = 23, which is correct

RTC_DR:MU[8..11] = 0b0110 = 6

RTC_DR:MT[12] = 0b0 = 0

=> month = 6, which is correct

day of week is not relevant for me

RTC_DR:YU[16..19] = 0b0101 = 5

RTC_DR:YT[20..23] = 0b0011 = 3

=> the year becomes 35, but I wrote 25 ...

 

And the solution is:

you have to initialize d and t from my intial posting to zero: 

RTC_DateTypeDef d = {0,};
RTC_TimeTypeDef t = {0,};

or something gets messed up and obviously some register segments get overwritten.

Saket_Om
ST Employee

Hello @CBerg 

Please refer to the example RTC_TimeStamp in the stm32CubeH7 package.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.
Saket_Om

Thanks for your input, @Saket_Om 

the issue is resolved. The mistake was, that I did not initialize the variables I used for setting the Clock to Zero.