STM32f103 and measuring of LSI frequency
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-09 5: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->cyccnt- Labels:
-
RTC
-
STM32F1 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-09 7: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 KHzUp vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-09 11:21 PM
Unfortunately, only SYSCLK, HSE, HSI and PLLCLK/2 are connected to MCO on STM32F103C8.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-10 6:08 AM
May be I'm thinking of the RTC TAMPER pin...
Up vote any posts that you find helpful, it shows what's working..
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-11 5: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
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2016-01-11 9: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
Up vote any posts that you find helpful, it shows what's working..
