2016-01-09 05:45 PM
Hello,
I'm trying to use LSI for RTC, but can't calculate correct prescaler value for RTC. And for each time I got different results(~+/-15sec. for each 2minutes), when test it. I found note in Reference manual (7.2.5 LSI clock Note) for STM32F103C8T6 that said: LSI measuring is only available for high-density, XL-density and connectivity line devices. Is exist some possibility to measuring of LSI frequency for STM32F103C8T6, for use this value to calculate RTC prescaler? Code for configure RTS with LIS:RCC->
APB1ENR
|= RCC_APB1ENR_BKPEN | RCC_APB1ENR_PWREN;
//Enable the APB1 backup domain and power
PWR->
CR
|= PWR_CR_DBP;
//Enable access to backup domain
RCC->
CSR
|= RCC_CSR_LSION;
//LSI 40k oscillator enabled
while
((RCC->
CSR
& RCC_CSR_LSIRDY) == 0);
//LSI ready
RCC->BDCR
|= RCC_BDCR_RTCSEL_LSI;
//Select LSE as the RTC clock source
RCC->
BDCR
|= RCC_BDCR_RTCEN;
//Enable the RTC clock
wait_sync();
//Poll the RSF bit in the RTC_CRL register until the RTC registers are synchronized
RTC->
CRL
&= ~RTC_CRL_RTOFF;
wait_ready
();
//Poll the RTOFF bit in the RTC_CRL register until the last operation on the RTC registers is over
/*
RTC->CRH |= RTC_CRH_SECIE;
NVIC->ISER[0] = NVIC_ISER_SETENA_3;
NVIC->IABR[0] |= NVIC_IABR_ACTIVE_3;
*/
RTC->
CRH
&= ~RTC_CRH_SECIE;
RTC->
CRH
&= ~RTC_CRH_OWIE;
RTC->
CRH
&= ~RTC_CRH_ALRIE;
RTC->
CRL
|= RTC_CRL_CNF;
//enter into RTC configuration mode
RTC->
PRLH
= 0;
RTC->
PRLL
= 40000-1;
//set iterations count for 1 second, LSI = 40k(39.967Hz)
RTC->
CNTH
= 0x0000;
//reset RTC value
RTC->
CNTL
= 0x0000;
//reset RTC value
RTC->
CRL
&= ~RTC_CRL_CNF;
//exit form RTC configuration mode
while
((RCC->
BDCR
& RCC_BDCR_RTCEN) != RCC_BDCR_RTCEN);
PWR->
CR
&= ~PWR_CR_DBP;
// disable access to RTC registers
#rcc_bdcr_rtcen #stm32f103c8t6 #dwt->cyccnt2016-01-09 07:13 PM
Later STM32 designs make it easier. Perhaps you can loop it externally via MCO (PA8) to a timer and measure against HSE.
You could also use a 32-bit counter like DWT_CYCCNT, and time stamp the RTC 1 Hz with nominal settings, and then tune the base on that estimate.Seem to remember some of mine being closer to 37 KHz2016-01-09 11:21 PM
Unfortunately, only SYSCLK, HSE, HSI and PLLCLK/2 are connected to MCO on STM32F103C8.
2016-01-10 06:08 AM
May be I'm thinking of the RTC TAMPER pin...
2016-01-11 05:07 AM
Thanks clive1,
I'm using DWT_CYCCNT for calculate LSI frequency on first RTC init. But this method is uncomfortable and complicated for using it few times. For my STM32F103C8, LSI works on ~969kHz(sometime: 940kHz-260kHz). I review docs(Ref. manual and AN2604) about TAMPER(PC13) calibration. But I do not found any information where stored TAMPER value, and how get this value after BKP->RTCCR |= BKP_RTCCR_CCO flag was set. Hire is code on DWT counter:
#define HSI_CLOCK_FREQUENCY 16000000
#define RTC_CALIBRATION_DIVIDER 25
#define RTC_CALIBRATION_CYC_COUNT HSI_CLOCK_FREQUENCY/RTC_CALIBRATION_DIVIDER
void
setupHSI() {
RCC->CR |= RCC_CR_HSION;
//Enable HSI
while
((RCC_CR_HSIRDY)==0);
//Wait HSI stabilization
RCC->CFGR |= RCC_CFGR_SW_HSI;
//HSI selected as system clock
RCC->CFGR |= RCC_CFGR_SWS_HSI;
//HSI oscillator used as system clock
while
((RCC_CR_HSIRDY)==0);
//Wait HSI stabilization
}
void
setPeriodAndClearCounter(uint32_t period) {
if
(60000<period)period=60000;
RTC->CRL |= RTC_CRL_CNF;
//enter into RTC configuration mode
RTC->PRLH = period >> 16;
RTC->PRLL = period;
//set period for RTC counter incrementation
RTC->CNTH = RTC->CNTL = 0;
//reset RTC counter value
RTC->CRL &= ~RTC_CRL_CNF;
//exit form RTC configuration mode
}
void
calibrate() {
uint32_t cycCnt, rtcValue;
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
//enable dwt counter
DWT->CYCCNT = 0;
//reset dwt counter
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
//start dwt counter
setPeriodAndClearCounter(1);
while
((cycCnt=DWT->CYCCNT) <= RTC_CALIBRATION_CYC_COUNT);
//repeats count = 16MHz/25 = 640k
rtcValue = ((RTC->CNTH << 16) | RTC->CNTL);
//read RTC counter value
DWT->CTRL &= ~DWT_CTRL_CYCCNTENA_Msk;
//stop dwt counter
CoreDebug->DEMCR &= ~CoreDebug_DEMCR_TRCENA_Msk;
//disable dwt counter
setPeriodAndClearCounter(rtcValue*RTC_CALIBRATION_DIVIDER);
//calculate LSI speed RTC result * 25 and set RTC deriver
}
2016-01-11 09:23 AM
I might approach that a bit differently, but the LSI clock is not at all stable, and you have very little control over the temperature/voltage