Skip to main content
Wassini
Associate II
October 19, 2021
Question

RTC drifting - a lot!

  • October 19, 2021
  • 7 replies
  • 4547 views

I have bought a STL8L Discovery kit and have installed the example for showing a clock: RTC using LSE - but it drift appx. 5 seconds per minute.

Seems like a simple 555 timer - or a cheap old analog clock - is more precise.

    This topic has been closed for replies.

    7 replies

    Peter BENSCH
    ST Technical Moderator
    October 19, 2021

    it looks as if you are not using the crystal-stabilized LSE, but by accident the RC-based LSI. Its frequency can vary between 26...56kHz, which corresponds to an RTC "error" of -20.6...+70.9%, i.e. about -12...+42s. Where did you find the sample program?

    Regards

    /Peter

    In order 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.
    Wassini
    WassiniAuthor
    Associate II
    October 19, 2021

    From http://wwwst.com/stm8l -> STM8l15x_StdPeriph_Lib.zip\Project\STM8L15x_StdPeriph_Examples\RTC\

    CLK_DeInit();
     
    CLK_LSEConfig(CLK_LSE_ON); /* Enable LSE */
     
    while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET); /* Wait for LSE clock to be ready */
     
    LSE_StabTime(); /* wait for 1 second for the LSE Stabilisation */
     
    CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);	// Low Speed External 
     
    CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);			// Enable RTC
     
    RTC_DeInit();
     
    RTC_StructInit(&rtc_init);
    errStatus = RTC_Init(&rtc_init);	
     
    RTC_DateStructInit(&rtc_date);
    errStatus = RTC_SetDate(RTC_Format_BIN, &rtc_date);

    Tesla DeLorean
    Guru
    October 19, 2021

    Make sure you set the prescalers appropriately

    RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;

    RTC_InitStr.RTC_AsynchPrediv = 127;

    RTC_InitStr.RTC_SynchPrediv = 255;

    RTC_Init(&RTC_InitStr);

    Suggest you read-back/dump the registers you currently run with to confirm the mode/settings, and that they are in fact correct and appropriate.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Tesla DeLorean
    Guru
    October 19, 2021
    void init_rtc(void)
    {
    	RTC_InitTypeDef RTC_InitStr;
    	RTC_TimeTypeDef RTC_TimeStr;
    	RTC_DateTypeDef RTC_DateStr;
     
    #if 0
    	/* LSI */
    	CLK_RTCClockConfig(CLK_RTCCLKSource_LSI, CLK_RTCCLKDiv_1);
    	CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
     
    	RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;
    	RTC_InitStr.RTC_AsynchPrediv = 0x7C;
    	RTC_InitStr.RTC_SynchPrediv = 0x012F;
    	RTC_Init(&RTC_InitStr);
    #else
    	/* LSE */
    	CLK_LSEConfig(CLK_LSE_ON);
    	while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET);
    	CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
    	CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
     
    	RTC_InitStr.RTC_HourFormat = RTC_HourFormat_24;
    	RTC_InitStr.RTC_AsynchPrediv = 127;
    	RTC_InitStr.RTC_SynchPrediv = 255;
    	RTC_Init(&RTC_InitStr);
    #endif
     
    	RTC_TimeStructInit(&RTC_TimeStr);
    	RTC_TimeStr.RTC_Hours = 00;
    	RTC_TimeStr.RTC_Minutes = 00;
    	RTC_TimeStr.RTC_Seconds = 00;
    	RTC_SetTime(RTC_Format_BIN, &RTC_TimeStr);
     
    	RTC_DateStructInit(&RTC_DateStr);
    	RTC_DateStr.RTC_WeekDay = RTC_Weekday_Tuesday;
    	RTC_DateStr.RTC_Date = 19;
    	RTC_DateStr.RTC_Month = RTC_Month_October;
    	RTC_DateStr.RTC_Year = 21;
    	RTC_SetDate(RTC_Format_BIN, &RTC_DateStr);
    }
     
    void rtc_get_time(char *buf)
    {
    	RTC_TimeTypeDef RTC_TimeStr;
     
    	while (RTC_WaitForSynchro() != SUCCESS);
     
    	RTC_GetTime(RTC_Format_BIN, &RTC_TimeStr);
     
    	sprintf(buf, "%02d:%02d:%02d",
    		RTC_TimeStr.RTC_Hours & 0xff, RTC_TimeStr.RTC_Minutes & 0xff, RTC_TimeStr.RTC_Seconds & 0xff);
    }
     
    void rtc_get_date(char *buf)
    {
    	RTC_DateTypeDef RTC_DateStr;
     
    	while (RTC_WaitForSynchro() != SUCCESS);
     
    	RTC_GetDate(RTC_Format_BIN, &RTC_DateStr);
     
    	sprintf(buf, "%04d-%02d-%02d",
    		(RTC_DateStr.RTC_Year & 0xff) + 2000, RTC_DateStr.RTC_Month & 0xff, RTC_DateStr.RTC_Date & 0xff);
    }

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Peter BENSCH
    ST Technical Moderator
    October 19, 2021

    It looks like inspired by the example RTC_Calendar.

    There are at least two possibilities: you either changed the clock assignment later, or the RTC automatically switched to LSI due to an error (see datasheet, section 3.5).

    Regards

    /Peter

    In order 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.
    Wassini
    WassiniAuthor
    Associate II
    December 9, 2021

    Hi. Sorry - have been working on other projects - but I still haven't got this working.

    Now I have copied the code from the "Discovery Board Demo", but I still can figure out how to change to LSE

    I have tried to remove all function calls and defined types just to see if this was causing any problems. When debugging I get an error in line 22.

    // Switch the clock to LSE 
    void init_LSE() 
    {
     
     // CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
    	// CLK_LSEConfig(CLK_LSE_ON);
     // CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSE);	// Switch in LSE clock 
     // CLK_SYSCLKSourceSwitchCmd(ENABLE);
     
    	CLK->CKDIVR = (uint8_t)(0x00); // Set the System clock divider to 1
    	
    	CLK->ECKCR &= (uint8_t)~0x04; // Reset LSEON bit
    	CLK->ECKCR &= (uint8_t)~0x20; // Reset LSEBYP bit
    	CLK->ECKCR |= (uint8_t)0x04;	// Configure LSE 
    	
    	delay_ms(2000);	
     
     while (!((CLK->ECKCR)& 0x08));	// Wait flag LSE ready 
     
    	CLK->SWR = (uint8_t)0x08;				// Switch in LSE clock 
     
    	CLK->SWCR |= (uint8_t)0x02; 		// Set SWEN bit - CLK_CKDIVR
     while (((CLK->SWCR)& 0x01)==0x01);
     
    }