cancel
Showing results for 
Search instead for 
Did you mean: 

RTC drifting - a lot!

Wassini
Associate II

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.

7 REPLIES 7
Peter BENSCH
ST Employee

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
Associate II

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);

Peter BENSCH
ST Employee

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.

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
Up vote any posts that you find helpful, it shows what's working..
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
Up vote any posts that you find helpful, it shows what's working..

Yes - thats my code!

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);
 
}