2018-01-28 02:48 AM
I want to use the Unix Epoch timestamp to configure the STM32 internal RTC to keep it synced up with network time. Can you advise how I can convert/use the milliseconds since 1970 Jan 1 to be applied to the internal RTC using CubeMX+HAL libraries?
Thank you!
#stm32-stm32cube #stm32f4-cube #rtc-cube #rtc-hal #stm32-f42018-01-28 08:39 AM
Which STM32?
32-bit UNIX time reflects seconds, not milliseconds. Milliseconds would wrap in 49 days.
You can crack UNIX time/date using gmtime(), most people would be safest using the libaray
The conversion back can be done reasonably efficiently, I used unsigned as it works beyond 2038
//****************************************************************************
unsigned int UNIXTime(int Day, int Month, int Year, int Hour, int Minute, int Second)
{// Month 1-12
mailto:sourcer32@gmail.com
// Year 1970-2099 (Fails >28-Feb-2100, Not a leap year, 2106 breaks 32-bit)if (Month <= 2)
{ Year--; Month += 12; }Day = ((36525 * Year) / 100) + ((306001 * (Month + 1)) / 10000) + Day - 719606;
Second += (Minute * 60) + (Hour * 3600);
return(((unsigned int)Day * (24 * 60 * 60)) + (unsigned int)Second);
}//****************************************************************************
Most date based RTC implementations are good 1901-2099, where all DIV4 years are leap, beyond this they usually break.
The STM32F1 has a 32-bit counter RTC, I've used UNIX time directly on it.
2018-01-28 09:59 AM
That is exactly what I was looking for, seconds will be sufficient for me.
I will need to use this on an STM32F429ZI, on an STM32F746NG and on an STM32L100RCT6.
2018-01-28 03:20 PM
void updateRTC(time_t now)
{
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
struct tm time_tm;
time_tm = *(localtime(&now));
sTime.Hours = (uint8_t)time_tm.tm_hour;
sTime.Minutes = (uint8_t)time_tm.tm_min;
sTime.Seconds = (uint8_t)time_tm.tm_sec;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
if (time_tm.tm_wday == 0) { time_tm.tm_wday = 7; } // the chip goes mon tue wed thu fri sat sun
sDate.WeekDay = (uint8_t)time_tm.tm_wday;
sDate.Month = (uint8_t)time_tm.tm_mon+1; //momth 1- This is why date math is frustrating.
sDate.Date = (uint8_t)time_tm.tm_mday;
sDate.Year = (uint16_t)(time_tm.tm_year+1900-2000); // time.h is years since 1900, chip is years since 2000
/*
* update the RTC
*/
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
HAL_RTCEx_BKUPWrite(&hrtc,RTC_BKP_DR0,0x32F2); // lock it in with the backup registers
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
and if you want to go the other direction,
RTC_DateTypeDef rtcDate;
RTC_TimeTypeDef rtcTime;
HAL_RTC_GetTime(&hrtc, &rtcTime, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &rtcDate, RTC_FORMAT_BIN);
uint8_t hh = rtcTime.Hours;
uint8_t mm = rtcTime.Minutes;
uint8_t ss = rtcTime.Seconds;
uint8_t d = rtcDate.Date;
uint8_t m = rtcDate.Month;
uint16_t y = rtcDate.Year;
uint16_t yr = (uint16_t)(y+2000-1900);
time_t currentTime = {0};
struct tm tim = {0};
tim.tm_year = yr;
tim.tm_mon = m - 1;
tim.tm_mday = d;
tim.tm_hour = hh;
tim.tm_min = mm;
tim.tm_sec = ss;
currentTime = mktime(&tim);
struct tm printTm = {0};
printTm = *(localtime(¤tTime));
char buffer[80];
strftime(buffer,80,'RTC %m/%d/%y %H:%M:%S', &printTm);
printf('%s
', buffer);�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
When using the standard c library to do time/date math, you have two data types and function calls. localtime() lets you go from time_t, which is seconds from new years 1900, to struct tm, which is a struct with everything broken out. localtime() to go from a time_t data type to a struct tm, and mktime() to go from a struct tm data type to time_t.