2025-06-22 10:08 AM
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!
Solved! Go to Solution.
2025-06-23 2:45 AM
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.
2025-06-22 11:52 PM - edited 2025-06-22 11:59 PM
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
}
2025-06-23 12:58 AM - edited 2025-06-23 2:10 AM
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.
2025-06-23 2:37 AM
Hello @CBerg
Please refer to the example RTC_TimeStamp in the stm32CubeH7 package.
2025-06-23 2:45 AM
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.