STM32:TIM定时中断配置的最全库函数讲解笔记

2024-09-01 05:28

本文主要是介绍STM32:TIM定时中断配置的最全库函数讲解笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        声明:本博客为哔哩哔哩up主@江协科技 “STM32入门教程”的听课笔记,仅供学习、参考使用,不得用作其他用途,违者必究。如有版权问题,请联系作者修改。

目录

一、综述

二、TIM库

初始化

2.1、TIM_DeInit 恢复缺省值

2.2、TIM_TimeBaseInit 时基单元初始化

2.3、 TIM_TimeBaseStructInit 时基单元结构体默认赋值

2.4、TIM_Cmd 使能计数器

2.5、TIM_ITConfig 使能中断输出信号

2.6、TIM_InternalClockConfig 选择内部时钟

2.7、TIM_ITRxExternalClockConfig

2.8、TIM_TIxExternalClockConfig

2.9、TIM_ETRClockMode1Config

2.10、TIM_ETRClockMode2Config

2.11、TIM_ETRConfig

2.12、6~11讲解

2.13、TIM结构体讲解

2.13.1、TIM_ClockDivision

2.13.2、TIM_CounterMode

2.13.3、TIM_Period

2.13.4、TIM_Prescaler

2.13.5、TIM_RepetitionCounter

参数变更

2.14、TIM_PrescalerConfig 单独写入预分频值

2.15、TIM_CounterModeConfig 改变计数器的计数模式

2.16、TIM_ARRPreloadConfig自动重装器预装功能配置

2.17、TIM_SetCounter 给计数器写入一个值

2.18、TIM_SetAutoreload 写入自动重装值

2.19、TIM_GetCounter 获取当前计数器的值

2.20、TIM_GetPrescaler 获取当前分频器的值

2.21、TIM_GetFlagStatus 主程序标志位获取

2.22、TIM_ClearFlag 主程序中清除标志位

2.23、TIM_GetITStatus 中断程序中获取标志位

2.24、TIM_ClearITPendingBit 中断程序中清除标志位

三、定时中断完整代码

3.1、Timer.h

3.2、Timer.c

3.2.1、具体步骤

3.2.2、完整代码

3.3、main.c

四、一个问题

五、定时中断完整代码(调整后)

5.1、Timer.h

5.2、Timer.c

5.2.1、具体步骤

5.2.2、完整代码

5.3、main.c


一、综述

上图是定时中断的整个框架结构。我们只需要把这里面的每个模块都打通,就可以让定时器工作了。

        具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

二、TIM库

初始化

2.1、TIM_DeInit 恢复缺省值

        函数原型:void TIM_DeInit(TIM_TypeDef* TIMx);

        函数讲解恢复缺省配置

        函数定义

/*** @brief  Deinitializes the TIMx peripheral registers to their default reset values.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @retval None*/
void TIM_DeInit(TIM_TypeDef* TIMx)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx)); if (TIMx == TIM1){RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);  }     else if (TIMx == TIM2){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE);}else if (TIMx == TIM3){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE);}else if (TIMx == TIM4){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE);} else if (TIMx == TIM5){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);} else if (TIMx == TIM6){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE);} else if (TIMx == TIM7){RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE);} else if (TIMx == TIM8){RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE);}else if (TIMx == TIM9){      RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE);  }  else if (TIMx == TIM10){      RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE);  }  else if (TIMx == TIM11) {     RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE);  }  else if (TIMx == TIM12){      RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, DISABLE);  }  else if (TIMx == TIM13) {       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, DISABLE);  }else if (TIMx == TIM14) {       RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, ENABLE);RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, DISABLE);  }        else if (TIMx == TIM15){RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, DISABLE);} else if (TIMx == TIM16){RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, DISABLE);} else{if (TIMx == TIM17){RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, ENABLE);RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, DISABLE);}  }
}

2.2、TIM_TimeBaseInit 时基单元初始化

        函数原型:

                        void TIM_TimeBaseInit(TIM_TypeDef* TIMx,

                        TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

        函数讲解:时基单元初始化;两个参数:第一个TIMx选择某个定时器,第二个是结构体,里面包含了配置时基单元的一些参数。

        函数定义

/*** @brief  Initializes the TIMx Time Base Unit peripheral according to *         the specified parameters in the TIM_TimeBaseInitStruct.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef*         structure that contains the configuration information for the *         specified TIM peripheral.* @retval None*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{uint16_t tmpcr1 = 0;/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx)); assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));tmpcr1 = TIMx->CR1;  if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||(TIMx == TIM4) || (TIMx == TIM5)) {/* Select the Counter Mode */tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;}if((TIMx != TIM6) && (TIMx != TIM7)){/* Set the clock division */tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;}TIMx->CR1 = tmpcr1;/* Set the Autoreload value */TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;/* Set the Prescaler value */TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))  {/* Set the Repetition Counter value */TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;}/* Generate an update event to reload the Prescaler and the Repetition countervalues immediately */TIMx->EGR = TIM_PSCReloadMode_Immediate;           
}

2.3、 TIM_TimeBaseStructInit 时基单元结构体默认赋值

        函数原型:

        void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

        函数讲解:这个函数可以把结构体变量赋一个默认值。

        函数定义

/*** @brief  Fills each TIM_TimeBaseInitStruct member with its default value.* @param  TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef*         structure which will be initialized.* @retval None*/
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{/* Set the default configuration */TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF;TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000;TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000;
}

2.4、TIM_Cmd 使能计数器

        函数原型:void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

        函数讲解:这个函数是用来使能计数器的,对应图中的“运行控制”板块。它有两个参数,第一个TIMx选择定时器,第二个NewState新的状态,也就是使能还是失能。使能的话,计数器就可以运行,失能的话,计数器就不能运行。

        函数定义

/*** @brief  Enables or disables the specified TIM peripheral.* @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.* @param  NewState: new state of the TIMx peripheral.*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Enable the TIM Counter */TIMx->CR1 |= TIM_CR1_CEN;}else{/* Disable the TIM Counter */TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));}
}

2.5、TIM_ITConfig 使能中断输出信号

        函数原型:

        void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); 

        函数讲解:这个是用来使能中断输出信号的,对应图中的“中断输出控制”。第一个参数TIMx,选择定时器;第二个参数TIM_IT,选择要配置哪个中断输出;第三个参数新的状态,使能还是失能。这种IT_Config之后会经常遇到,就是使能外设的中断输出。

        第二个参数可以是下面这些值的任意组合

  *     @arg TIM_IT_Update: TIM update Interrupt source*     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source*     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source*     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source*     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source*     @arg TIM_IT_COM: TIM Commutation Interrupt source*     @arg TIM_IT_Trigger: TIM Trigger Interrupt source*     @arg TIM_IT_Break: TIM Break Interrupt source

        函数定义

/*** @brief  Enables or disables the specified TIM interrupts.* @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.* @param  TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.*   This parameter can be any combination of the following values:*     @arg TIM_IT_Update: TIM update Interrupt source*     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source*     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source*     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source*     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source*     @arg TIM_IT_COM: TIM Commutation Interrupt source*     @arg TIM_IT_Trigger: TIM Trigger Interrupt source*     @arg TIM_IT_Break: TIM Break Interrupt source* @note *   - TIM6 and TIM7 can only generate an update interrupt.*   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,*      TIM_IT_CC2 or TIM_IT_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    * @param  NewState: new state of the TIM interrupts.*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
{  /* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_IT(TIM_IT));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Enable the Interrupt sources */TIMx->DIER |= TIM_IT;}else{/* Disable the Interrupt sources */TIMx->DIER &= (uint16_t)~TIM_IT;}
}

2.6、TIM_InternalClockConfig 选择内部时钟

        函数原型:void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

        函数讲解:选择内部时钟。参数只有一个TIMx。

        函数定义

/*** @brief  Configures the TIMx internal Clock* @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15*         to select the TIM peripheral.* @retval None*/
void TIM_InternalClockConfig(TIM_TypeDef* TIMx)
{/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));/* Disable slave mode to clock the prescaler directly with the internal clock */TIMx->SMCR &=  (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
}

2.7、TIM_ITRxExternalClockConfig

        函数原型:

        void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_InputTriggerSource);

        函数讲解选择ITR其他定时器的时钟。第一个参数是TIMx,选择要配置的定时器,二个参s数是TIM_InputTriggerSource,选择要接入哪个其他的定时器。

        函数定义

/*** @brief  Configures the TIMx Internal Trigger as External Clock* @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.* @param  TIM_ITRSource: Trigger source.*   This parameter can be one of the following values:* @param  TIM_TS_ITR0: Internal Trigger 0* @param  TIM_TS_ITR1: Internal Trigger 1* @param  TIM_TS_ITR2: Internal Trigger 2* @param  TIM_TS_ITR3: Internal Trigger 3* @retval None*/
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
{/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource));/* Select the Internal Trigger */TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource);/* Select the External clock mode1 */TIMx->SMCR |= TIM_SlaveMode_External1;
}

2.8、TIM_TIxExternalClockConfig

        函数原型:

        void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

        函数讲解选择TIx捕获通道的时钟,第一个参数TIMx选择需要配置的定时器;第二个参数TIM_TIxExternalCLKSource,选择TIx具体的某个引脚;第三个参数TIM_ICPolarity输入的极性;第四个参数ICFilter,输入的滤波器。对于外部引脚的波形,一般都会有极性选择和滤波器,这样更灵活一些。

        函数定义

/*** @brief  Configures the TIMx Trigger as External Clock* @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.* @param  TIM_TIxExternalCLKSource: Trigger source.*   This parameter can be one of the following values:*     @arg TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector*     @arg TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1*     @arg TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2* @param  TIM_ICPolarity: specifies the TIx Polarity.*   This parameter can be one of the following values:*     @arg TIM_ICPolarity_Rising*     @arg TIM_ICPolarity_Falling* @param  ICFilter : specifies the filter value.*   This parameter must be a value between 0x0 and 0xF.* @retval None*/
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter)
{/* Check the parameters */assert_param(IS_TIM_LIST6_PERIPH(TIMx));assert_param(IS_TIM_TIXCLK_SOURCE(TIM_TIxExternalCLKSource));assert_param(IS_TIM_IC_POLARITY(TIM_ICPolarity));assert_param(IS_TIM_IC_FILTER(ICFilter));/* Configure the Timer Input Clock Source */if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2){TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);}else{TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);}/* Select the Trigger source */TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource);/* Select the External clock mode1 */TIMx->SMCR |= TIM_SlaveMode_External1;
}

2.9、TIM_ETRClockMode1Config

        函数原型:

        void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx,

                 uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

        函数原型选择ETR通过外部时钟模式1输入的时钟。第二个参数TIM_ExtTRGPrescaler,外部触发预分频器,可以对ETR的外部时钟再提前做一个分频,第三个参数TIM_ExtTRGPolarity输入的极性,第四个参数ExtTRGFilter输入的滤波器。

        函数定义

/*** @brief  Configures the External clock Mode1* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.*     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.*     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.*     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.* @param  TIM_ExtTRGPolarity: The external Trigger Polarity.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.*     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.* @param  ExtTRGFilter: External Trigger Filter.*   This parameter must be a value between 0x00 and 0x0F* @retval None*/
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter)
{uint16_t tmpsmcr = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));/* Configure the ETR Clock source */TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);/* Get the TIMx SMCR register value */tmpsmcr = TIMx->SMCR;/* Reset the SMS Bits */tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));/* Select the External clock mode1 */tmpsmcr |= TIM_SlaveMode_External1;/* Select the Trigger selection : ETRF */tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));tmpsmcr |= TIM_TS_ETRF;/* Write to TIMx SMCR */TIMx->SMCR = tmpsmcr;
}

2.10、TIM_ETRClockMode2Config

        函数原型:

        void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx,

                 uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

        函数讲解

        选择ETR通过外部时钟模式2输入的时钟。参数同上。对于ETR输入的时钟而言,9和10两个函数是等效的,它们的参数也是一样的。如果不需要触发输入的功能,那两个函数可以互换。

        函数定义

/*** @brief  Configures the External clock Mode2* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.*     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.*     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.*     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.* @param  TIM_ExtTRGPolarity: The external Trigger Polarity.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.*     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.* @param  ExtTRGFilter: External Trigger Filter.*   This parameter must be a value between 0x00 and 0x0F* @retval None*/
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)
{/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));/* Configure the ETR Clock source */TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);/* Enable the External clock mode2 */TIMx->SMCR |= TIM_SMCR_ECE;
}

2.11、TIM_ETRConfig

        函数原型:

        void TIM_ETRConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,

                        uint16_t ExtTRGFilter);

        函数讲解单独用来配置ETR引脚的预分频器、极性、滤波器这些参数的

        函数定义

/*** @brief  Configures the TIMx External Trigger (ETR).* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.*     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.*     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.*     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.* @param  TIM_ExtTRGPolarity: The external Trigger Polarity.*   This parameter can be one of the following values:*     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.*     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.* @param  ExtTRGFilter: External Trigger Filter.*   This parameter must be a value between 0x00 and 0x0F* @retval None*/
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter)
{uint16_t tmpsmcr = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));tmpsmcr = TIMx->SMCR;/* Reset the ETR Bits */tmpsmcr &= SMCR_ETR_Mask;/* Set the Prescaler, the Filter value and the Polarity */tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8)));/* Write to TIMx SMCR */TIMx->SMCR = tmpsmcr;
}

2.12、6~11讲解

        上面这六个函数对应的就是时基单元的时钟选择部分,可以选择RCC内部时钟、ETR外部时钟、ITRx其他定时器、TIx捕获通道等。

2.13、TIM结构体讲解

typedef struct
{uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.This parameter can be a number between 0x0000 and 0xFFFF */uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.This parameter can be a value of @ref TIM_Counter_Mode */uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the activeAuto-Reload Register at the next update event.This parameter must be a number between 0x0000 and 0xFFFF.  */ uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.This parameter can be a value of @ref TIM_Clock_Division_CKD */uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounterreaches zero, an update event is generated and counting restartsfrom the RCR value (N).This means in PWM mode that (N+1) corresponds to:- the number of PWM periods in edge-aligned mode- the number of half PWM period in center-aligned modeThis parameter must be a number between 0x00 and 0xFF. @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;   

2.13.1、TIM_ClockDivision

        指定时钟分频,参数可以是TIM_Clock_Division_CKD中的一个值。

        时钟分频的作用:

        在定时器的外部信号输入引脚, 一般都会有滤波器用来过滤掉信号抖动的干扰

        工作原理是:在一个固定的时钟频率f下进行采样,如果连续N个采样点都为相同的电平,那就代表输入信号稳定了,就把这个采样值输出出去;如果这N个采样值不全都相同,那就说明信号有抖动,这时就保持上一次的输出或者直接输出低电平。这样就能保证输出信号在一定程度上的滤波

        这里的采样频率f和采样点数N都是滤波器的参数。频率越低,采样点数越多,滤波效果越好,不过相应的信号延迟就越大

         滤波器的采样频率f的来源:STM32手册中声明它可以由内部时钟直接而来,也可以是由内部时钟加一个时钟分频而来。分频多少就是由这个参数TIM_ClockDivision决定的。

        (这个参数和时基单元关系并不大)

 TIM_Clock_Division_CKD:

/** @defgroup TIM_Clock_Division_CKD * @{*/#define TIM_CKD_DIV1                       ((uint16_t)0x0000)
#define TIM_CKD_DIV2                       ((uint16_t)0x0100)
#define TIM_CKD_DIV4                       ((uint16_t)0x0200)

        TIM_CKD_DIV1是1分频,即不分频;

        TIM_CKD_DIV2是2分频;

        TIM_CKD_DIV4是4分频;

2.13.2、TIM_CounterMode

        计数器模式。TIM_CounterMode可以是TIM_Counter_Mode中的一个值。

/** @defgroup TIM_Counter_Mode * @{*/#define TIM_CounterMode_Up                 ((uint16_t)0x0000)
#define TIM_CounterMode_Down               ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)
#define IS_TIM_COUNTER_MODE(MODE) (((MODE) == TIM_CounterMode_Up) ||  \((MODE) == TIM_CounterMode_Down) || \((MODE) == TIM_CounterMode_CenterAligned1) || \((MODE) == TIM_CounterMode_CenterAligned2) || \((MODE) == TIM_CounterMode_CenterAligned3))

         从上到下分别是向上计数、向下计数、三种中央对齐模式。

2.13.3、TIM_Period

        周期,就是ARR自动重装器的值。时基单元中关键寄存器的参数之一。

        计算方法:

        注意:

        1.预分频器和计数器都有一个数的偏差,所以使用的时候要-1。、

        2.PSC和ARR的取值都要在0~65535之间,不要超出范围

        3.PSC和ARR的取值不是唯一的。可以预分频值给少一点、自动重装给多一点,这样就是以一个比较高的频率计比较多的数;也可以预分频值给多一点、自动重装给少一点,这样就是以一个比较低的频率计比较少的数。两种方法都可以达到目标的定时时间。

	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;

        在这里我们是对72MHz进行7200分频,得到的是10k的计数频率。 在10k的频率下计1w个数,正好是1s的时间。

2.13.4、TIM_Prescaler

        PSC预分频器的值。时基单元中关键寄存器的参数之一。

2.13.5、TIM_RepetitionCounter

        重复计数器的值。时基单元中关键寄存器的参数之一。是高级定时器才有的。

参数变更

2.14、TIM_PrescalerConfig 单独写入预分频值

        函数原型:

        void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,

                uint16_t TIM_PSCReloadMode);

        函数讲解

        这个函数是用来单独写预分频值的。第一个参数Prescaler就是要写入的预分频值,第二个参数TIM_PSCReloadMode是指写入的模式。

        预分频器有一个缓冲器,写入的值是在更新时间发生后才有效的。所以这里有个写入的模式,可以选择听从安排,在更新事件生效,或者是在写入后手动产生一个更新事件,让这个值立刻生效。

        函数定义

/*** @brief  Configures the TIMx Prescaler.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  Prescaler: specifies the Prescaler Register value* @param  TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode*   This parameter can be one of the following values:*     @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event.*     @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately.* @retval None*/
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode));/* Set the Prescaler value */TIMx->PSC = Prescaler;/* Set or reset the UG Bit */TIMx->EGR = TIM_PSCReloadMode;
}

2.15、TIM_CounterModeConfig 改变计数器的计数模式

        函数原型:void TIM_CounterModeConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_CounterMode);

        函数讲解:这个函数用于改变计数器的计数模式。参数TIM_CounterMode选择新的计数器模式。

        函数定义

/*** @brief  Specifies the TIMx Counter Mode to be used.* @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.* @param  TIM_CounterMode: specifies the Counter Mode to be used*   This parameter can be one of the following values:*     @arg TIM_CounterMode_Up: TIM Up Counting Mode*     @arg TIM_CounterMode_Down: TIM Down Counting Mode*     @arg TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1*     @arg TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2*     @arg TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3* @retval None*/
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode)
{uint16_t tmpcr1 = 0;/* Check the parameters */assert_param(IS_TIM_LIST3_PERIPH(TIMx));assert_param(IS_TIM_COUNTER_MODE(TIM_CounterMode));tmpcr1 = TIMx->CR1;/* Reset the CMS and DIR Bits */tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));/* Set the Counter Mode */tmpcr1 |= TIM_CounterMode;/* Write to TIMx CR1 register */TIMx->CR1 = tmpcr1;
}

2.16、TIM_ARRPreloadConfig自动重装器预装功能配置

        函数原型:void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx,

                FunctionalState NewState);

        函数讲解

                自动重装器预装功能配置。有无预装是可以自己选择的

                选择方法:第二个参数NewState赋值为使能or失能。

 

        函数定义

/*** @brief  Enables or disables TIMx peripheral Preload register on ARR.* @param  TIMx: where x can be  1 to 17 to select the TIM peripheral.* @param  NewState: new state of the TIMx peripheral Preload register*   This parameter can be: ENABLE or DISABLE.* @retval None*/
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_FUNCTIONAL_STATE(NewState));if (NewState != DISABLE){/* Set the ARR Preload Bit */TIMx->CR1 |= TIM_CR1_ARPE;}else{/* Reset the ARR Preload Bit */TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);}
}

2.17、TIM_SetCounter 给计数器写入一个值

        函数原型:void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

        函数讲解给计数器写入一个值。如果想手动给一个计数值,就可以用这个函数。

        函数定义

/*** @brief  Sets the TIMx Counter Register value* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  Counter: specifies the Counter register new value.* @retval None*/
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));/* Set the Counter Register value */TIMx->CNT = Counter;
}

2.18、TIM_SetAutoreload 写入自动重装值

        函数原型:void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

        函数讲解给自动重装器写入一个值。如果想手动给一个自动重装值,就可以用这个函数。

        函数定义

/*** @brief  Sets the TIMx Autoreload Register value* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  Autoreload: specifies the Autoreload register new value.* @retval None*/
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));/* Set the Autoreload Register value */TIMx->ARR = Autoreload;
}

2.19、TIM_GetCounter 获取当前计数器的值

        函数原型:uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

        函数讲解获取当前计数器的值。如果想要查看当前计数器计到哪里了,就可以调用一下这个函数,返回当前计数器的值。

        函数定义

/*** @brief  Gets the TIMx Counter value.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @retval Counter Register value.*/
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));/* Get the Counter Register value */return TIMx->CNT;
}

2.20、TIM_GetPrescaler 获取当前分频器的值

        函数原型:uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

        函数讲解获取当前的预分频器的值。如果想看预分频值,就调用一下这个函数。

        函数定义

/*** @brief  Gets the TIMx Prescaler value.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @retval Prescaler Register value.*/
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));/* Get the Prescaler Register value */return TIMx->PSC;
}

2.21、TIM_GetFlagStatus 主程序标志位获取

        函数原型:FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

        函数讲解:主程序中获取标志位。

        函数定义

/*** @brief  Checks whether the specified TIM flag is set or not.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_FLAG: specifies the flag to check.*   This parameter can be one of the following values:*     @arg TIM_FLAG_Update: TIM update Flag*     @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag*     @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag*     @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag*     @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag*     @arg TIM_FLAG_COM: TIM Commutation Flag*     @arg TIM_FLAG_Trigger: TIM Trigger Flag*     @arg TIM_FLAG_Break: TIM Break Flag*     @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag*     @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag*     @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag*     @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag* @note*   - TIM6 and TIM7 can have only one update flag. *   - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,*      TIM_FLAG_CC2 or TIM_FLAG_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.   *   - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    * @retval The new state of TIM_FLAG (SET or RESET).*/
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{ ITStatus bitstatus = RESET;  /* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_GET_FLAG(TIM_FLAG));if ((TIMx->SR & TIM_FLAG) != (uint16_t)RESET){bitstatus = SET;}else{bitstatus = RESET;}return bitstatus;
}

2.22、TIM_ClearFlag 主程序中清除标志位

        函数原型:void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

        函数讲解主程序中清除标志位。

        函数定义

/*** @brief  Clears the TIMx's pending flags.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_FLAG: specifies the flag bit to clear.*   This parameter can be any combination of the following values:*     @arg TIM_FLAG_Update: TIM update Flag*     @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag*     @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag*     @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag*     @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag*     @arg TIM_FLAG_COM: TIM Commutation Flag*     @arg TIM_FLAG_Trigger: TIM Trigger Flag*     @arg TIM_FLAG_Break: TIM Break Flag*     @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag*     @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag*     @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag*     @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag* @note*   - TIM6 and TIM7 can have only one update flag. *   - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,*      TIM_FLAG_CC2 or TIM_FLAG_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.   *   - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.   * @retval None*/
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{  /* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));/* Clear the flags */TIMx->SR = (uint16_t)~TIM_FLAG;
}

2.23、TIM_GetITStatus 中断程序中获取标志位

        函数原型:ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

        函数讲解中断程序中获取标志位

        函数定义

/*** @brief  Checks whether the TIM interrupt has occurred or not.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_IT: specifies the TIM interrupt source to check.*   This parameter can be one of the following values:*     @arg TIM_IT_Update: TIM update Interrupt source*     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source*     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source*     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source*     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source*     @arg TIM_IT_COM: TIM Commutation Interrupt source*     @arg TIM_IT_Trigger: TIM Trigger Interrupt source*     @arg TIM_IT_Break: TIM Break Interrupt source* @note*   - TIM6 and TIM7 can generate only an update interrupt.*   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,*      TIM_IT_CC2 or TIM_IT_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.  * @retval The new state of the TIM_IT(SET or RESET).*/
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{ITStatus bitstatus = RESET;  uint16_t itstatus = 0x0, itenable = 0x0;/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_GET_IT(TIM_IT));itstatus = TIMx->SR & TIM_IT;itenable = TIMx->DIER & TIM_IT;if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET)){bitstatus = SET;}else{bitstatus = RESET;}return bitstatus;
}

2.24、TIM_ClearITPendingBit 中断程序中清除标志位

        函数原型:void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

        函数讲解中断程序中清除标志位

        函数定义

/*** @brief  Clears the TIMx's interrupt pending bits.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_IT: specifies the pending bit to clear.*   This parameter can be any combination of the following values:*     @arg TIM_IT_Update: TIM1 update Interrupt source*     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source*     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source*     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source*     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source*     @arg TIM_IT_COM: TIM Commutation Interrupt source*     @arg TIM_IT_Trigger: TIM Trigger Interrupt source*     @arg TIM_IT_Break: TIM Break Interrupt source* @note*   - TIM6 and TIM7 can generate only an update interrupt.*   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,*      TIM_IT_CC2 or TIM_IT_Trigger. *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    * @retval None*/
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_IT(TIM_IT));/* Clear the IT pending Bit */TIMx->SR = (uint16_t)~TIM_IT;
}

三、定时中断完整代码

3.1、Timer.h

#ifndef _TIMER_H
#define _TIMER_Hvoid timer_init(void);#endif

3.2、Timer.c

3.2.1、具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

	/*第一步:配置rcc时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

TIM_InternalClockConfig(TIM2);

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;/*中断通道*/NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

TIM_Cmd(TIM2,ENABLE); 

3.2.2、完整代码

#include "stm32f10x.h"                  // Device headerextern uint16_t num;void timer_init(void)
{/*第一步:配置rcc时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);/*配置时基单元*/TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);/*使能更新中断*/TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*此时已经开启了更新中断到NVIC的通路*//*配置NVIC通路*//*NVIC优先级分组:*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;/*中断通道*/NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/*启动定时器*/TIM_Cmd(TIM2,ENABLE); 
}void TIM2_IRQHandler(void)
{/*检查中断标志位*/if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}

3.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t num;
int main(void)
{OLED_Init();timer_init();/*初始化定时器*/OLED_ShowString(1, 1, "num:");while (1){OLED_ShowNum(1,5,num,5);OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5); }
}

四、一个问题

        烧录代码观察现象,发现num是从1开始计数的。但是num的初始值为0,按理说应该是从0开始计数的,但是num一经上电就立刻变为1了,说明中断函数在初始化后就立刻进入了一次

        在TIM_TimeBaseInit的函数定义中:

/*** @brief  Initializes the TIMx Time Base Unit peripheral according to *         the specified parameters in the TIM_TimeBaseInitStruct.* @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.* @param  TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef*         structure that contains the configuration information for the *         specified TIM peripheral.* @retval None*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{uint16_t tmpcr1 = 0;/* Check the parameters */assert_param(IS_TIM_ALL_PERIPH(TIMx)); assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));tmpcr1 = TIMx->CR1;  if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||(TIMx == TIM4) || (TIMx == TIM5)) {/* Select the Counter Mode */tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;}if((TIMx != TIM6) && (TIMx != TIM7)){/* Set the clock division */tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;}TIMx->CR1 = tmpcr1;/* Set the Autoreload value */TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;/* Set the Prescaler value */TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))  {/* Set the Repetition Counter value */TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;}/* Generate an update event to reload the Prescaler and the Repetition countervalues immediately */TIMx->EGR = TIM_PSCReloadMode_Immediate;           
}

        其中最后一行代码上面的注释:

           /* Generate an update event to reload the Prescaler and the Repetition counter values immediately */

        翻译为:立刻生成一个更新事件,来重新装载预分频器和重复计数器的值

        TIM_TimeBaseInit函数中有 “TIMx->EGR = TIM_PSCReloadMode_Immediate;”这句的原因是:

        预分频器是有一个缓冲寄存器的,我们写入的值只有在更新事件时才会真正起作用。所以这里为了让值立刻起作用,就在函数的最后手动生成了一个更新事件,这样,预分频器的值就有效了。

        但同时,它的副作用就是更新事件和更新中断是同时发生的,更新中断会置更新标志位。当我们之后一旦初始化结束,更新中断就会立刻进入。这就是我们刚一上电就立刻进入中断的原因

        解决方法

        在TIM_TimeBaseInit()的后面,开启中断的前面,调用一下TIM_ClearFlag()函数,手动将TIM_FLAG_Update更新标志位清除一下,就能避免刚初始化结束就立刻进入中断的问题了。

五、定时中断完整代码(调整后)

5.1、Timer.h

#ifndef _TIMER_H
#define _TIMER_Hvoid timer_init(void);#endif

5.2、Timer.c

5.2.1、具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

TIM_InternalClockConfig(TIM2);

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

	/*使能更新中断*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;/*中断通道*/NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

TIM_Cmd(TIM2,ENABLE); 

5.2.2、完整代码

#include "stm32f10x.h"                  // Device headerextern uint16_t num;void timer_init(void)
{/*第一步:配置rcc时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);/*配置时基单元*/TIM_InternalClockConfig(TIM2);TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);/*使能更新中断*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*此时已经开启了更新中断到NVIC的通路*//*配置NVIC通路*//*NVIC优先级分组:*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;/*中断通道*/NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/*启动定时器*/TIM_Cmd(TIM2,ENABLE); 
}void TIM2_IRQHandler(void)
{/*检查中断标志位*/if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET){num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}

5.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"uint16_t num;
int main(void)
{OLED_Init();timer_init();/*初始化定时器*/OLED_ShowString(1, 1, "num:");while (1){OLED_ShowNum(1,5,num,5);OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5); }
}

这篇关于STM32:TIM定时中断配置的最全库函数讲解笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1126061

相关文章

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

第10章 中断和动态时钟显示

第10章 中断和动态时钟显示 从本章开始,按照书籍的划分,第10章开始就进入保护模式(Protected Mode)部分了,感觉从这里开始难度突然就增加了。 书中介绍了为什么有中断(Interrupt)的设计,中断的几种方式:外部硬件中断、内部中断和软中断。通过中断做了一个会走的时钟和屏幕上输入字符的程序。 我自己理解中断的一些作用: 为了更好的利用处理器的性能。协同快速和慢速设备一起工作

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

让树莓派智能语音助手实现定时提醒功能

最初的时候是想直接在rasa 的chatbot上实现,因为rasa本身是带有remindschedule模块的。不过经过一番折腾后,忽然发现,chatbot上实现的定时,语音助手不一定会有响应。因为,我目前语音助手的代码设置了长时间无应答会结束对话,这样一来,chatbot定时提醒的触发就不会被语音助手获悉。那怎么让语音助手也具有定时提醒功能呢? 我最后选择的方法是用threading.Time

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识