2014-07-28 12:38 PM
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 #rtc2014-07-28 10:01 PM
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....2014-07-29 09:22 AM
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
2014-07-29 11:39 AM
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, Gary2014-07-29 12:09 PM
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
2014-07-29 12:38 PM
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
2014-07-29 01:00 PM
#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 );
}
2014-07-29 01:11 PM
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, Gary2014-07-29 01:37 PM
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.