Reputation: 33
I wanted to get uptime of the system from the RTC in seconds. The point is that while I can sum up values from the RTC time register (RTC_TR) it only works up to 24 hours and then overflows while one day is being added to RTC date register (RTC_DR).
How do I count seconds from the time I start up the system? I don't need the calendar.
Below the explaination of what do I mean by "overflow"
I've configured RTC according to STM's RTC_LSI example for StdPeriph and set only the time and not the date.
However when I get the time from RTC_TR using RTC_GetTime function, after 23h59m59s, the time goes back to 0h0m0s.
Of course RTC_TR holds time in its BCD format in tens and units of current hour, minute and second and days are counted in RTC_DR. Anyway I'd like it to keep on adding hours and not to add the days to the date register as I want to calculate only uptime and I'm afraid that if I started counting the months and days I'd have problems.
void RtcConfig(void)
{
RTC_InitTypeDef RTC_InitStructure;
RTC_TimeTypeDef RTC_TimeStructure;
RTC_DateTypeDef RTC_DateStructure;
uint32_t LSIFreq = 0;
/* Enable the PWR clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
/* Allow access to Backup Domain */
PWR_BackupAccessCmd(ENABLE);
/* Disable wake-up source(ALARM) to guarantee free access to WUT level-OR input */
RTC_ITConfig(RTC_IT_ALRA, DISABLE);
/* Clear Wakeup flag */
PWR_ClearFlag(PWR_FLAG_WU);
/* Enable wake-up source(ALARM) to guarantee free access to WUT level-OR input */
RTC_ITConfig(RTC_IT_ALRA, ENABLE);
/* Enable the LSI OSC */
RCC_LSICmd(ENABLE);
/* Wait till LSI is ready */
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
{}
/* Check if the StandBy flag is set (leaving stand-by) */
if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)
{
/* Clear StandBy flag */
PWR_ClearFlag(PWR_FLAG_SB);
/* Check if the StandBy flag is cleared */
if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)
{
while(1);
}
RTC_WaitForSynchro();
/* No need to configure the RTC as the RTC config(clock source, enable,
prescaler,...) are kept after wake-up from STANDBY */
}
else
{
/* RTC Configuration ******************************************************/
/* Reset Backup Domain */
RCC_BackupResetCmd(ENABLE);
RCC_BackupResetCmd(DISABLE);
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Get the LSI frequency: TIM14 is used to measure the LSI frequency */
LSIFreq = GetLSIFrequency();
RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
RTC_InitStructure.RTC_AsynchPrediv = 99;
RTC_InitStructure.RTC_SynchPrediv = (LSIFreq/100) - 1;
RTC_Init(&RTC_InitStructure);
/* Set the time to 00h 00mn 00s AM */
RTC_TimeStructure.RTC_H12 = RTC_H12_PM;
RTC_TimeStructure.RTC_Hours = 0;
RTC_TimeStructure.RTC_Minutes = 0;
RTC_TimeStructure.RTC_Seconds = 0;
RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure);
}
}
uint32 GetLSIFrequency(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
TIM_ICInitTypeDef TIM_ICInitStructure;
RCC_ClocksTypeDef RCC_ClockFreq;
/* TIM14 configuration *******************************************************/
/* Enable TIM14 clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE);
/* Reset TIM14 registers */
TIM_DeInit(TIM14);
/* Configure TIM14 prescaler */
TIM_PrescalerConfig(TIM14, 0, TIM_PSCReloadMode_Immediate);
/* Connect internally the TIM14_CH1 to the RTC clock output */
TIM_RemapConfig(TIM14, TIM14_RTC_CLK);
/* TIM14 configuration: Input Capture mode ---------------------
The reference clock(LSE or external) is connected to TIM14 CH1
The Rising edge is used as active edge,
The TIM14 CCR1 is used to compute the frequency value
------------------------------------------------------------ */
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV8;
TIM_ICInitStructure.TIM_ICFilter = 0x0;
TIM_ICInit(TIM14, &TIM_ICInitStructure);
/* Enable the TIM14 global Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable TIM14 counter */
TIM_Cmd(TIM14, ENABLE);
/* Reset the flags */
TIM14->SR = 0;
/* Enable the CC1 Interrupt Request */
TIM_ITConfig(TIM14, TIM_IT_CC1, ENABLE);
/* Wait until the TIM14 get 2 LSI edges (refer to TIM14_IRQHandler() in
stm32F0xx_it.c file) ******************************************************/
while(CaptureNumber != 2)
{
}
/* Deinitialize the TIM14 peripheral registers to their default reset values */
TIM_DeInit(TIM14);
/* Compute the LSI frequency, depending on TIM14 input clock frequency (PCLK1)*/
/* Get SYSCLK, HCLK and PCLKx frequency */
RCC_GetClocksFreq(&RCC_ClockFreq);
/* Disable TIM14 counter */
TIM_Cmd(TIM14, DISABLE);
TIM_ITConfig(TIM14, TIM_IT_CC1, DISABLE);
/* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */
return ((RCC_ClockFreq.PCLK_Frequency / PeriodValue) * 8);
}
void RTC_GetTime(uint32_t RTC_Format, RTC_TimeTypeDef* RTC_TimeStruct)
{
uint32_t tmpreg = 0;
/* Check the parameters */
assert_param(IS_RTC_FORMAT(RTC_Format));
/* Get the RTC_TR register */
tmpreg = (uint32_t)(RTC->TR & RTC_TR_RESERVED_MASK);
/* Fill the structure fields with the read parameters */
RTC_TimeStruct->RTC_Hours = (uint8_t)((tmpreg & (RTC_TR_HT | RTC_TR_HU)) >> 16);
RTC_TimeStruct->RTC_Minutes = (uint8_t)((tmpreg & (RTC_TR_MNT | RTC_TR_MNU)) >>8);
RTC_TimeStruct->RTC_Seconds = (uint8_t)(tmpreg & (RTC_TR_ST | RTC_TR_SU));
RTC_TimeStruct->RTC_H12 = (uint8_t)((tmpreg & (RTC_TR_PM)) >> 16);
/* Check the input parameters format */
if (RTC_Format == RTC_Format_BIN)
{
/* Convert the structure parameters to Binary format */
RTC_TimeStruct->RTC_Hours = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Hours);
RTC_TimeStruct->RTC_Minutes = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Minutes);
RTC_TimeStruct->RTC_Seconds = (uint8_t)RTC_Bcd2ToByte(RTC_TimeStruct->RTC_Seconds);
}
}
uint32 RtcGetTimeSec(void)
{
RTC_TimeTypeDef RTC_TimeStructure;
uint32 currenttimesec = 0;
/* Get the Current time in second */
RTC_GetTime(RTC_Format_BIN, &RTC_TimeStructure);
currenttimesec = ((RTC_TimeStructure.RTC_Hours * 3600) +(RTC_TimeStructure.RTC_Minutes * 60) +
RTC_TimeStructure.RTC_Seconds);
return currenttimesec;
}
Upvotes: 0
Views: 2365
Reputation: 67516
What does it mean overflows. Show your code & maths
In 32bits you can store:
Seconds Hours Days Years
4294967295 1193046.471 49710.26962 136.1925195
If your predicted up-time is more than 136.2 years use 64bit unsigned integer and you wil be able to count up to:
Seconds Hours Days Years Decades Centuries Millenniums Aeons (10e9 years)
18446744073709600000 5124095576030430 213503982334601 584942417355 58494241736 5849424174 584942417 585
Hope that will be enough yor you.
Upvotes: 2