/** * @brief Configures TIM5 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ uint32_t GetLSIFrequency(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_ClocksTypeDef RCC_ClockFreq; mico_rtos_init_semaphore(&_measureLSIComplete_SEM, 1); /* Enable the LSI oscillator ************************************************/ RCC_LSICmd(ENABLE); /* Wait till LSI is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} /* TIM5 configuration *******************************************************/ /* Enable TIM5 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); /* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */ TIM_RemapConfig(TIM5, TIM5_LSI); /* Configure TIM5 presclaer */ TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate); /* TIM5 configuration: Input Capture mode --------------------- The LSI oscillator is connected to TIM5 CH4 The Rising edge is used as active edge, The TIM5 CCR4 is used to compute the frequency value ------------------------------------------------------------ */ TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; 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 = 0; TIM_ICInit(TIM5, &TIM_ICInitStructure); /* Enable TIM5 Interrupt channel */ NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 15; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable TIM5 counter */ TIM_Cmd(TIM5, ENABLE); /* Reset the flags */ TIM5->SR = 0; /* Enable the CC4 Interrupt Request */ TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE); /* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler()) *********/ mico_rtos_get_semaphore(&_measureLSIComplete_SEM, MICO_WAIT_FOREVER); /* Deinitialize the TIM5 peripheral registers to their default reset values */ TIM_ITConfig(TIM5, TIM_IT_CC4, DISABLE); TIM_DeInit(TIM5); NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 5; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 8; NVIC_InitStructure.NVIC_IRQChannelCmd = DISABLE; NVIC_Init(&NVIC_InitStructure); /* Compute the LSI frequency, depending on TIM5 input clock frequency (PCLK1)*/ /* Get SYSCLK, HCLK and PCLKx frequency */ RCC_GetClocksFreq(&RCC_ClockFreq); /* Get PCLK1 prescaler */ if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0) { /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue) * 8); } else { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */ return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue) * 8) ; } }
/** * @brief Configures TIM5 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ uint32_t GetLSIFrequency(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; /* Enable the LSI oscillator ************************************************/ RCC_LSICmd(ENABLE); /* Wait till LSI is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} /* TIM5 configuration *******************************************************/ /* Enable TIM5 clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); /* Connect internally the TIM5_CH4 Input Capture to the LSI clock output */ TIM_RemapConfig(TIM5, TIM5_LSI); /* Configure TIM5 presclaer */ TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate); /* TIM5 configuration: Input Capture mode --------------------- The LSI oscillator is connected to TIM5 CH4 The Rising edge is used as active edge, The TIM5 CCR4 is used to compute the frequency value ------------------------------------------------------------ */ TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; 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 = 0; TIM_ICInit(TIM5, &TIM_ICInitStructure); /* Enable TIM5 Interrupt channel */ NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable TIM5 counter */ TIM_Cmd(TIM5, ENABLE); /* Reset the flags */ TIM5->SR = 0; /* Enable the CC4 Interrupt Request */ TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE); /* Wait until the TIM5 get 2 LSI edges (refer to TIM5_IRQHandler() in stm32fxxx_it.c file) ******************************************************/ while(CaptureNumber != 2) { } /* Deinitialize the TIM5 peripheral registers to their default reset values */ TIM_DeInit(TIM5); /* Get PCLK1 prescaler */ if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0) { /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return (((SystemCoreClock/4) / PeriodValue) * 8); } else { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */ return (((2 * (SystemCoreClock/4)) / PeriodValue) * 8) ; } }
/** * @brief Configures TIM14 to measure the LSI oscillator frequency. * @param None * @retval None */ void TIM14_ConfigForLSI(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; /* Enable peripheral clocks ------------------------------------------------*/ RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE); /* Allow access to the RTC */ PWR_BackupAccessCmd(ENABLE); /* Reset RTC Domain */ RCC_BackupResetCmd(ENABLE); RCC_BackupResetCmd(DISABLE); /*!< LSI Enable */ RCC_LSICmd(ENABLE); /*!< Wait till LSI is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} /* 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(); /* Enable TIM14 clocks */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM14, ENABLE); /* Enable the TIM14 Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM14_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Configure TIM14 prescaler */ TIM_PrescalerConfig(TIM14, 0, TIM_PSCReloadMode_Immediate); /* Connect internally the TM14_CH1 Input Capture to the LSI clock output */ TIM_RemapConfig(TIM14, TIM14_RTC_CLK); /* TIM14 configuration: Input Capture mode --------------------- The LSI oscillator 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 = 0; TIM_ICInit(TIM14, &TIM_ICInitStructure); /* TIM14 Counter Enable */ TIM_Cmd(TIM14, ENABLE); /* Reset the flags */ TIM14->SR = 0; /* Enable the CC1 Interrupt Request */ TIM_ITConfig(TIM14, TIM_IT_CC1, ENABLE); }
/* ********************************************************************************************************* * 函 数 名: GetLSIFrequency * 功能说明: 配置TIM5的通道4测试LSI频率 * 形 参:无 * 返 回 值: LSI Frequency 实际测试LSI = 34000左右,手册上面给的范围是 ********************************************************************************************************* */ static uint32_t GetLSIFrequency(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_ClocksTypeDef RCC_ClockFreq; /* 使能外部低速晶振 */ RCC_LSICmd(ENABLE); /* 等待直到LSI就绪 */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) {} /* TIM5 配置 */ /* 使能TIM5时钟 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5, ENABLE); /* 将TIM5_CH4输入捕获通道连接到LSI时钟输出 */ TIM_RemapConfig(TIM5, TIM5_LSI); /* 配置TIM5分频 */ TIM_PrescalerConfig(TIM5, 0, TIM_PSCReloadMode_Immediate); /* TIM5 配置: 输入捕获模式 1. LSI 振荡器连接到 TIM5 CH4 2. 上升沿做为激活的边沿 3. TIM5 CCR4用于计算频率值 4. 这里主要分频设置TIM_ICPSC_DIV8,它的意思不是TIM的8分频 它的意思是每8个时间捕获一次,这里就表示8个上升沿以后是 一次捕获进入中断,然后再过8个上升沿捕获一次进入中断,这两 次中断以后得到时间间隔,也就是8个周期,所以最后得到的结果 是放大了8倍。 */ TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; 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 = 0; TIM_ICInit(TIM5, &TIM_ICInitStructure); /* 使能TIM5中断通道 */ NVIC_InitStructure.NVIC_IRQChannel = TIM5_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* 使能TIM5计数 */ TIM_Cmd(TIM5, ENABLE); /* 清除标志 */ TIM5->SR = 0; /* 使能 CC4 中断请求 */ TIM_ITConfig(TIM5, TIM_IT_CC4, ENABLE); /* 等待直到 TIM5 得到 2 个LSI 边沿 */ while(CaptureNumber != 2) { } /* 重定义TIM5到复位值 */ TIM_DeInit(TIM5); /* 计算 LSI 频率, 根据TIM5输入时钟频率做计算(PCLK1)*/ /* 得到 SYSCLK, HCLK 和 PCLKx */ RCC_GetClocksFreq(&RCC_ClockFreq); /* HCLK = SYSCLK / 1 (AHB1Periph) = 168MHz PCLK2 = HCLK / 2 (APB2Periph) = 84MHz PCLK1 = HCLK / 4 (APB1Periph) = 42MHz 因为APB1 prescaler != 1, 所以 APB1上的TIMxCLK = PCLK1 x 2 = SystemCoreClock / 2; 因为APB2 prescaler != 1, 所以 APB2上的TIMxCLK = PCLK2 x 2 = SystemCoreClock; APB1 定时器有 TIM2, TIM3 ,TIM4, TIM5, TIM6, TIM6, TIM12, TIM13,TIM14 APB2 定时器有 TIM1, TIM8 ,TIM9, TIM10, TIM11 */ if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0) { /* 如果PCLK1 prescaler == 1 那么 TIMCLK = PCLK1 */ return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue)*8); } else { /* 如果PCLK1 prescaler 不等于 1 那么 TIMCLK = 2 * PCLK1 这里设置乘以8是因为前面设置每8个事件产生一次捕获。 */ return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue)*8) ; } }
/** * @brief Configures TIM14 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ static uint32_t 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); /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return ((RCC_ClockFreq.PCLK_Frequency / PeriodValue) * 8); }
/** * @brief Configures TIM10 to measure the LSI oscillator frequency. * @param None * @retval LSI Frequency */ uint32_t GetLSIFrequency(void) { NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; RCC_ClocksTypeDef RCC_ClockFreq; /* Enable the LSI oscillator ************************************************/ RCC_LSICmd(ENABLE); /* Wait till LSI is ready */ while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET) { } /* TIM10 configuration *******************************************************/ /* Enable TIM10 clocks */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM10, ENABLE); /* Connect internally the TIM10_CH1 Input Capture to the LSI clock output */ TIM_RemapConfig(TIM10, TIM10_LSI); /* Configure TIM10 presclaer */ TIM_PrescalerConfig(TIM10, 0, TIM_PSCReloadMode_Immediate); /* TIM10 configuration: Input Capture mode --------------------- The LSI oscillator is connected to TIM10 CH1 The Rising edge is used as active edge, The TIM10 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 = 0; TIM_ICInit(TIM10, &TIM_ICInitStructure); /* Enable TIM10 Interrupt channel */ NVIC_InitStructure.NVIC_IRQChannel = TIM10_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* Enable TIM10 counter */ TIM_Cmd(TIM10, ENABLE); /* Reset the flags */TIM10->SR = 0; /* Enable the CC1 Interrupt Request */ TIM_ITConfig(TIM10, TIM_IT_CC1, ENABLE); /* Wait until the TIM10 get 2 LSI edges (refer to TIM10_IRQHandler() in stm32l1xx_it.c file) ******************************************************/ while (CaptureNumber != 2) { } /* Deinitialize the TIM10 peripheral registers to their default reset values */ TIM_DeInit(TIM10); /* Compute the LSI frequency, depending on TIM10 input clock frequency (PCLK1)*/ /* Get SYSCLK, HCLK and PCLKx frequency */ RCC_GetClocksFreq(&RCC_ClockFreq); /* Get PCLK1 prescaler */ if ((RCC->CFGR & RCC_CFGR_PPRE1) == 0) { /* PCLK1 prescaler equal to 1 => TIMCLK = PCLK1 */ return ((RCC_ClockFreq.PCLK1_Frequency / PeriodValue) * 8); } else { /* PCLK1 prescaler different from 1 => TIMCLK = 2 * PCLK1 */ return (((2 * RCC_ClockFreq.PCLK1_Frequency) / PeriodValue) * 8); } }