Dear friends, I have a problem when reading counter register of RTC in STM32F103RB. After resetting the MCU, the value starts from zero. I have a 3V backup battery connected to VBAT pin. My code to config RTC is in below
void RTC_Config(void) { /* Enable PWR and BKP clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* Allow access to BKP Domain */ PWR_BackupAccessCmd(ENABLE); /* Reset Backup Domain */ BKP_DeInit(); /* Enable LSE */ RCC_LSEConfig(RCC_LSE_ON); /* Wait till LSE is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} /* Select LSE as RTC Clock Source */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); /* Enable RTC Clock */ RCC_RTCCLKCmd(ENABLE); /* Wait for RTC registers synchronization */ RTC_WaitForSynchro(); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); /* Enable the RTC Second */ RTC_ITConfig(RTC_IT_SEC, ENABLE); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); /* Set RTC prescaler: set RTC period to 1sec */ RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */ /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); //---------------------------------------------------- }
in main function:
rtc_val=RTC_GetCounter();
Solution:I missed to comment following lines
/* Reset Backup Domain */ //BKP_DeInit();
Now RTC works fine! following is my complete code:
//RTC.c #include "rtc.h" #include "main.h" #include "stm32f10x.h" #include "stm32f10x_rtc.h" #include <stdio.h> #include "math.h" #include <time.h> //--------------------------------------------------------------- static struct skew { int8_t error; uint8_t ticks; } skew; /* The calendar "tm" structure from the standard libray "time.h" has the following definition: */ //struct tm //{ // int tm_sec; /* seconds, range 0 to 59 */ // int tm_min; /* minutes, range 0 to 59 */ // int tm_hour; /* hours, range 0 to 23 */ // int tm_mday; /* day of the month, range 1 to 31 */ // int tm_mon; /* month, range 0 to 11 */ // int tm_year; /* The number of years since 1900 */ // int tm_wday; /* day of the week, range 0 to 6 */ // int tm_yday; /* day in the year, range 0 to 365 */ // int tm_isdst; /* daylight saving time */ //}; struct tm calendar_time_cache; // a cache of calendar time structure elements time_t unix_time_cache; // a cache of unix_time that was updated time_t time_zone_cache; // a cache of the time zone that was set /* Time utility functions */ static struct tm Convert_UnixTime_To_CalendarTime(time_t unix_time); static time_t Convert_CalendarTime_To_UnixTime(struct tm calendar_time); static time_t Get_UnixTime(void); static struct tm Get_CalendarTime(void); static void Set_UnixTime(time_t unix_time); static void Set_CalendarTime(struct tm t); static void Refresh_UnixTime_Cache(time_t unix_time); //------------------------------------------------------------------------------------ /* Convert Unix/RTC time to Calendar time */ static struct tm Convert_UnixTime_To_CalendarTime(time_t unix_time) { struct tm *calendar_time; unix_time += time_zone_cache; calendar_time = localtime(&unix_time); calendar_time->tm_year += 1900; return *calendar_time; } /* Convert Calendar time to Unix/RTC time */ static time_t Convert_CalendarTime_To_UnixTime(struct tm calendar_time) { calendar_time.tm_year -= 1900; time_t unix_time = mktime(&calendar_time); return unix_time; } /* Get Unix/RTC time */ static time_t Get_UnixTime(void) { time_t unix_time = (time_t)RTC_GetCounter(); return unix_time; } /* Get converted Calendar time */ static struct tm Get_CalendarTime(void) { time_t unix_time = Get_UnixTime(); unix_time += time_zone_cache; struct tm calendar_time = Convert_UnixTime_To_CalendarTime(unix_time); return calendar_time; } /* Set Unix/RTC time */ static void Set_UnixTime(time_t unix_time) { RTC_WaitForLastTask(); RTC_SetCounter((uint32_t)unix_time); RTC_WaitForLastTask(); } /* Set Calendar time as Unix/RTC time */ static void Set_CalendarTime(struct tm calendar_time) { Set_UnixTime(Convert_CalendarTime_To_UnixTime(calendar_time)); } /* Refresh Unix/RTC time cache */ static void Refresh_UnixTime_Cache(time_t unix_time) { if(unix_time != unix_time_cache) { calendar_time_cache = Convert_UnixTime_To_CalendarTime(unix_time); unix_time_cache = unix_time; } } //---------------------------------------------------------------------------------- void set_time(struct tm calendar_time) { Set_CalendarTime(calendar_time); } struct tm get_time(void) { timestamp clock; uint32_t rtc_val; rtc_val=RTC_GetCounter(); time_t rawtime=rtc_val; struct tm *info; /* Get GMT time */ info = gmtime(&rawtime ); return *info; } void RTC_Config(void) { /* Enable PWR and BKP clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); /* Allow access to BKP Domain */ PWR_BackupAccessCmd(ENABLE); /* Reset Backup Domain */ //BKP_DeInit(); /* Enable LSE */ RCC_LSEConfig(RCC_LSE_ON); /* Wait till LSE is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) {} /* Select LSE as RTC Clock Source */ RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); /* Enable RTC Clock */ RCC_RTCCLKCmd(ENABLE); /* Wait for RTC registers synchronization */ RTC_WaitForSynchro(); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); /* Enable the RTC Second */ RTC_ITConfig(RTC_IT_SEC, ENABLE); /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); /* Set RTC prescaler: set RTC period to 1sec */ RTC_SetPrescaler(32767); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767+1) */ /* Wait until last write operation on RTC registers has finished */ RTC_WaitForLastTask(); //---------------------------------------------------- }
struct tm calendar_time; calendar_time.tm_sec=1; calendar_time.tm_min=1; calendar_time.tm_hour=15; calendar_time.tm_mday=21; calendar_time.tm_mon=5; calendar_time.tm_year=2016; set_time(calendar_time); while(1) { rtc=get_time(); sprintf(str,"%.2u:%.2u:%.2u",(rtc.tm_year-100),rtc.tm_mon,rtc.tm_mday); lcd_first_row(); lcd_print(str); delay_ms(10); lcd_second_row(); sprintf(str,"%.2u:%.2u:%.2u",rtc.tm_hour,rtc.tm_min,rtc.tm_sec); lcd_print(str); }