2018-04-12 08:59 AM
Hello,
I'm using a custom board with STM8L151K4 MCU on batteries. Everything works awesome, power consumption is minimal, state is active-halt (MCU is woken via a button) with RTC on. RTC is used with LSE, but trouble is that for several days in real time, RTC moves fast forward (seems to be accelerated somehow) with several days. For example: I set up the clock on 2018, checking it on 2018, it's already 2..
In my algorithm, I often have to change clock frequency when MCU is awaken from LSI to HSI (need some computational power for a short time) and then back to LSI. I couldn't find any information of whether it affects the RTC clock source which should be LSE all the time. Here are parts of my code:
void setSpeed(bool HighSpeed)
{
ReadyToSleep = FALSE;
tmrSet(FALSE);
if (HighSpeed)
{
if (CLK_GetSYSCLKSource() == CLK_SYSCLKSource_HSI)
{
tmrSet(TRUE);
return;
}
//CLK_MainRegulatorCmd(ENABLE);
//FLASH_PowerRunModeConfig(FLASH_Power_On);
//enable HSI
CLK_HSICmd(ENABLE);
//wait till hardware sets the flag
while (CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == 0) ;
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI) ;
CLK_SYSCLKSourceSwitchCmd(DISABLE);
//disable LSI as we don't need it anymore
CLK_LSICmd(DISABLE);
//10 ms interrupt on HSI
TIM4_TimeBaseInit(TIM4_Prescaler_2048, 77);
//10 ms interrupt on HSI /**/
}
else
{
if (CLK_GetSYSCLKSource() == CLK_SYSCLKSource_LSI)
{
//LED_RED_OFF;
tmrSet(TRUE);
return;
}
//enable HSI
CLK_LSICmd(ENABLE);
//wait till hardware sets the flag
while (CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == 0) ;
CLK_SYSCLKSourceSwitchCmd(ENABLE);
CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSI);
CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_LSI) ;
CLK_SYSCLKSourceSwitchCmd(DISABLE);
//disable HSI as we don't need it anymore
CLK_HSICmd(DISABLE);
//10 ms interrupt on LSI
TIM4_TimeBaseInit(TIM4_Prescaler_32, 10);
//10 ms interrupt on LSI /**/
}
tmrSet(TRUE);
//LED_RED_OFF;
}
void setup_clock(void)
{
//CLK_HSECmd(DISABLE);
TIM4_DeInit();
CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);
//disable all the peripherals, trying to achieve as low power consumption as possible
CLK_PeripheralClockConfig(CLK_Peripheral_LCD, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_USART1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_USART2, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_USART3, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_SPI2, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_BEEP, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_DAC, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_COMP, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_AES, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_CSSLSE, DISABLE);
//CLK_PeripheralClockConfig(CLK_Peripheral_RTC, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_BOOTROM, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, DISABLE);
//CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, DISABLE);
CLK_PeripheralClockConfig(CLK_Peripheral_TIM5, DISABLE);
TIM1->CR1 &= (uint8_t)(~TIM1_CR1_CEN);
TIM2->CR1 &= (uint8_t)(~TIM_CR1_CEN);
TIM3->CR1 &= (uint8_t)(~TIM_CR1_CEN);
//TIM4->CR1 &= (uint8_t)(~TIM_CR1_CEN);
TIM5->CR1 &= (uint8_t)(~TIM_CR1_CEN);
//disable all the peripherals, trying to achieve as low power consumption as possible
PWR_PVDCmd(DISABLE);
setSpeed(SPEED_LOW);
/* Set STM8 in low power */
//start the low speed external crystal
CLK_LSEConfig(CLK_LSE_ON);
//and wait till it's stable
while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET) ;
//set RTC divider to 1, i.e. RTS is running on 767 kHz
CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
//start the RTC itself
CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE);
PWR_UltraLowPowerCmd(ENABLE);
//setup RTC
//24-hour format. We myself don't like the 0-12 am/pm, so we always work with 0-24
//RTC_DeInit();
RTC_StructInit(&rtc);
rtc.RTC_HourFormat = RTC_HourFormat_24;
rtc.RTC_AsynchPrediv = 0x7F;
rtc.RTC_SynchPrediv = 0x00FF;
if (RTC_Init(&rtc) == ERROR)
{
//TODO:
//blink RED LED several times
SetLedRed(lmBlinkThree);
}
RTC_DateStructInit(¤tDateTime.date);
RTC_TimeStructInit(¤tDateTime.time);
RTC_ITConfig(RTC_IT_ALRA | RTC_IT_TAMP | RTC_IT_WUT, DISABLE);
RTC_AlarmCmd(DISABLE);
//setup RTC
TIM4_ITConfig(TIM4_IT_Update, ENABLE);
TIM4_ClearFlag(TIM4_FLAG_Update);
tmrSet(FALSE);
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
tmrSet is a function that starts or stops Timer 4 - nothing else. Setup_Clock() is called only once on MCU initialization (on start of the program), whereas setSpeed is called whenever I need to switch clock source.
Any suggestion will be highly appreciable.
Thanks in advance.
Regards,
Javor