Skip to main content
Rogers.Gary
Senior II
July 28, 2014
Question

Unable to Set RTC on STM32F4

  • July 28, 2014
  • 8 replies
  • 2362 views
Posted on July 28, 2014 at 21:38

Hi,

I'm following an example as provided by the STD PERIPHERALS library, on an STM32F4 Discovery board. In spite of what's being written in the config routine, when I set the define for LSI, I read back this:

Year =  20

Month =  07

Date =  36

Hours =  15

Mins =  32

Secs =  35

When I set the define for LSE, I read back this:

Year =  00

Month =  01

Date =  01

Hours =  00

Mins =  00

Secs =  00

Neither of which matches the values being written in the config routine. For the LSE, a 32.768KHz xtal was installed, with 2 caps, and is oscillating happily.

Here's the config routine:

&sharpdefine RTC_CLOCK_SOURCE_LSE            /* LSE used as RTC source clock */

&sharpdefine FIRST_DATA         0x32F2

static void RTC_Config(void)

{

    /* Enable the PWR clock */

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    /* Allow access to RTC */

    PWR_BackupAccessCmd(ENABLE);

    

    &sharpif defined (RTC_CLOCK_SOURCE_LSI)  /* LSI used as RTC source clock*/

    /* The RTC Clock may varies due to LSI frequency dispersion. */

      /* Enable the LSI OSC */

      RCC_LSICmd(ENABLE);

      /* Wait till LSI is ready */  

      while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)

      {

      }

      /* Select the LSI as RTC Clock Source */

      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);

      /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/

      uwSynchPrediv = 0xFF;

      uwAsynchPrediv = 0x7F;

    &sharpelif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */

      /* Enable the LSE OSC */

      RCC_LSEConfig(RCC_LSE_ON);

      /* Wait till LSE is ready */  

      while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

      {

      }

      /* Select the LSE as RTC Clock Source */

      RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

     /* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/

      uwSynchPrediv = 0xFF;

      uwAsynchPrediv = 0x7F;

    &sharpelse

      &sharperror Please select the RTC Clock source inside the main.c file

    &sharpendif /* RTC_CLOCK_SOURCE_LSI */

      

      /* Enable the RTC Clock */

      RCC_RTCCLKCmd(ENABLE);

      /* Wait for RTC APB registers synchronisation */

      RTC_WaitForSynchro();

      /* Write to the first RTC Backup Data Register */

      RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);

      /* Set the Time */

      RTC_TimeStructure.RTC_Hours   = 0x08;

      RTC_TimeStructure.RTC_Minutes = 0x00;

      RTC_TimeStructure.RTC_Seconds = 0x00;

      /* Set the Date */

      RTC_DateStructure.RTC_Month = RTC_Month_July;

      RTC_DateStructure.RTC_Date = 0x27;  

      RTC_DateStructure.RTC_Year = 0x14;

      RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Monday;

      /* Calendar Configuration */

      RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;

      RTC_InitStructure.RTC_SynchPrediv =  uwSynchPrediv;

      RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

      RTC_Init(&RTC_InitStructure);

      

      /* Set Current Time and Date */

      RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure);  

      RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);

}

I would be forever grateful if anyone....could tell me what the issue is. I have been in grief for a day now trying to figure out what is wrong. What i find really perplexing is, the routine above is directly from ST. Why doesnt it work on either LSI, or LSE?  Totally at a loss here....please HELP.

#stm32 #rtc
This topic has been closed for replies.

8 replies

Rogers.Gary
Senior II
July 29, 2014
Posted on July 29, 2014 at 07:01

Hi,

Can anyone who's got a working RTC configuration please post it here, or check mine out to see if they might know what the issue is? I really need to get this working.

Thanks....

Tesla DeLorean
Guru
July 29, 2014
Posted on July 29, 2014 at 18:22

Well, it works for me. Make sure you have the solder bridges removed, and you probe the clock indirectly via the MCO pin, or measure via TIM5

LSI:32080, LSE:32770
LSE On
LSE Ready
LSE ByPass Off
RTC Clock Enabled
RTC Clock Source LSE
08:00:00 27/07/14
08:00:01 27/07/14
08:00:02 27/07/14
08:00:03 27/07/14
08:00:04 27/07/14
08:00:05 27/07/14
08:00:06 27/07/14
08:00:07 27/07/14
08:00:08 27/07/14
08:00:09 27/07/14

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
July 29, 2014
Posted on July 29, 2014 at 20:39

Hi clive1,

Thank you for answering.

I had not removed the solder bridges. I have now done that, and ensured there was not any connection between the 2 points where they were. The oscillator I installed still appears to be working. I verified the MCU is getting the signal at pins 8 & 9.

However, the RTC still is not configuring...

Please forgive my ignorance. The documentation isn't clear about MCO. The only MCO connection is port PA8.

1 - If MCO is PA8, I am not getting any signal there. Is that the correct point to check?

2 - What should the frequency of the MCO be?

3 - How (& why) would I check with TIM5?

Thanks again,

Gary

Tesla DeLorean
Guru
July 29, 2014
Posted on July 29, 2014 at 21:09

I pasted in your code, though admittedly I have LSI and LSE running already, as part of my original test framework for the STM32F4-DISCO. I picked up a strip of the 768 KHz parts as most of the Disco boards don't have them, and standby works better from LSE. These need to be 6-7pF crystals, not the 9 or 12pF type. Sticking scope probes on the pins will alter the circuit characteristics.

There are two MCO pins on F2/F4 parts, you can route internal clocks and fractions thereof under 60-84MHz out. You can measure LSE directly, and should be 32768 Hz at DIV1.

void ClockMCO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure MCO (PA8) */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Output LSE clock (768KHz) on MCO pin (PA8) */
RCC_MCO1Config(RCC_MCO1Source_LSE, RCC_MCO1Div_1);
}

TIM5_CH4 can be routed to the RTC clock, and you can benchmark it for accuracy against the HSE/PLL, ie period of an LSE/LSI cycle in 8 or 168 MHz ticks. The code here misses a few tricks, but is illustrative : STM32F4xx_DSP_StdPeriph_Lib_V1.3.0\Project\STM32F4xx_StdPeriph_Examples\RTC\RTC_LSI\main.c
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
July 29, 2014
Posted on July 29, 2014 at 21:38

Clive1,

Again, thanks. I ran the test code you provided and there is a perfect square wave at the correct (LSE) frequency on PA8. Is it possible you can post 2 other things for me and I'll do some further testing? 1 - The function calls to display (in your original post) that displayed the following:

LSI:32080, LSE:32770
LSE On
LSE Ready
LSE ByPass Off
RTC Clock Enabled
RTC Clock Source LSE

2 - I know this sounds silly, but did you use the exact (RTC_Config) function I put at the start of this thread? If so, can you then tell me what calls you are using to display the date/time? Maybe that's where things are going weird. Not sure what else to look for at this point... Regards, Gary
Tesla DeLorean
Guru
July 29, 2014
Posted on July 29, 2014 at 22:00

#define RTC_CLOCK_SOURCE_LSE /* LSE used as RTC source clock */
#define FIRST_DATA 0x32F2
void RTC_Configuration(void)
{
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
uint32_t uwSynchPrediv, uwAsynchPrediv;
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to RTC */
PWR_BackupAccessCmd(ENABLE);
#if defined (RTC_CLOCK_SOURCE_LSI) /* LSI used as RTC source clock*/
/* The RTC Clock may varies due to LSI frequency dispersion. */
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */ 
while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{
}
/* Select the LSI as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
uwSynchPrediv = 0xFF;
uwAsynchPrediv = 0x7F;
#elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
/* Enable the LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */ 
while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
{
}
/* Select the LSE as RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* ck_spre(1Hz) = RTCCLK(LSE) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
uwSynchPrediv = 0xFF;
uwAsynchPrediv = 0x7F;
#else
#error Please select the RTC Clock source inside the main.c file
#endif /* RTC_CLOCK_SOURCE_LSI */
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Write to the first RTC Backup Data Register */
RTC_WriteBackupRegister(RTC_BKP_DR0, FIRST_DATA);
/* Set the Time */
RTC_TimeStructure.RTC_Hours = 0x08;
RTC_TimeStructure.RTC_Minutes = 0x00;
RTC_TimeStructure.RTC_Seconds = 0x00;
/* Set the Date */
RTC_DateStructure.RTC_Month = RTC_Month_July;
RTC_DateStructure.RTC_Date = 0x27; 
RTC_DateStructure.RTC_Year = 0x14;
RTC_DateStructure.RTC_WeekDay = RTC_Weekday_Monday;
/* Calendar Configuration */
RTC_InitStructure.RTC_AsynchPrediv = uwAsynchPrediv;
RTC_InitStructure.RTC_SynchPrediv = uwSynchPrediv;
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_Init(&RTC_InitStructure);
/* Set Current Time and Date */
RTC_SetTime(RTC_Format_BCD, &RTC_TimeStructure); 
RTC_SetDate(RTC_Format_BCD, &RTC_DateStructure);
if (RCC->BDCR & 0x1)
printf(''LSE On
'');
else
printf(''LSE Off
'');
if (RCC->BDCR & 0x2)
printf(''LSE Ready
'');
else
printf(''LSE Not Ready
'');
if (RCC->BDCR & 0x4)
printf(''LSE ByPass On
'');
else
printf(''LSE ByPass Off
'');
if (RCC->BDCR & 0x8000)
printf(''RTC Clock Enabled
'');
else
printf(''RTC Clock Disabled
'');
switch(RCC->BDCR & 0x300)
{
case 0x100 : puts(''RTC Clock Source LSE''); break;
case 0x200 : puts(''RTC Clock Source LSI''); break;
case 0x300 : printf(''RTC Clock Source HSE/%d'', (RCC->CFGR >> 16) & 0x1F); break;
default : puts(''RTC Clock Unknown'');
}
}
//******************************************************************************
void RTC_TimeShow(void)
{
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
/* Get the current Time */
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);
/* Display time Format : hh:mm:ss DD/MM/YY */
printf(''%0.2d:%0.2d:%0.2d %0.2d/%0.2d/%0.2d
'',
RTC_TimeStructure.RTC_Hours, RTC_TimeStructure.RTC_Minutes, RTC_TimeStructure.RTC_Seconds,
RTC_DateStructure.RTC_Date, RTC_DateStructure.RTC_Month, RTC_DateStructure.RTC_Year );
}

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
July 29, 2014
Posted on July 29, 2014 at 22:11

Hi Clive1...

Here's what you were doing:

RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);

RTC_GetDate(RTC_Format_BIN, &RTC_DateStructure);   This is the really dumb thing I was doing: RTC_GetTime(RTC_Format_BCD, &RTC_TimeStructure);

RTC_GetDate(RTC_Format_BCD, &RTC_DateStructure);   All good now (except the red shade of my face)   Thanks for being prompt, courteous and very helpful.   Regards,  Gary

Tesla DeLorean
Guru
July 29, 2014
Posted on July 29, 2014 at 22:37

You could use BCD and ''%02X'', as I recall the register are held in BCD (silicon is simpler), so going to binary(decimal) takes more compute cycles, but eases other math.

Personally I prefer the 32-bit RTC count of the F1 parts, but a lot of code to handle the calendering tends to get broken during implementation. ie Leap Years, Day-Of-Week, Day-Of-Year and human centric D/M/Y stuff.
Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..