配置定时/计数中断配置基本步骤:
一:开启RCC时钟:
TIMX所在总线:
STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4
由上面可知TIM2在APB1总线上:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//开启TIM2的RCC时钟
如果要使用引脚输入,还需要开启GPIO的时钟:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//开启GPIOA的RCC时钟
二:选择时钟源(CK_PSC):
选择时钟源函数:
TIM_InternalClockConfig函数:
/**
* @brief 选择内部时钟做为时钟源
* @param TIMx: 其中x可以是1 2 3 4 5 8 9 12或15(STM32c8t6仅能选择1,2,3,4)
* *选择要配置的定时器。
* @retval None
*/
void TIM_InternalClockConfig(TIM_TypeDef* TIMx)
TIM_ITRxExternalClockConfig函数:
/* *
* @brief选择ITRx其他定时器的时钟为时钟源
* @param TIMx:选择要配置的定时器,其中x可以是1、2、3、4、5、9、12或15。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_ITRSource:选择要接入其他哪个定时器。
*此参数可以是下列值之一:
* @param TIM_TS_ITR0:ITR0
* @param TIM_TS_ITR1:ITR1
* @param TIM_TS_ITR2:ITR2
* @param TIM_TS_ITR3:ITR3
* @retval无
*/
TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
定时器之间的具体连接见下图:
TIM_TIxExternalClockConfig函数:
/**
* @brief 选择ITx捕获通道的时钟为时钟源
* @param TIMx: 选择要配置的定时器,其中x可以是1、2、3、4、5、9、12或15来。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_TIxExternalCLKSource: 选择具体的TIx引脚。
* 此参数可以是下列值之一:
* @arg TIM_TIxExternalCLK1Source_TI1ED: TI1输入
* @arg TIM_TIxExternalCLK1Source_TI1: TI1FP1输入
* @arg TIM_TIxExternalCLK1Source_TI2: TI2FP2输入
* @param TIM_ICPolarity: 指定TIx极性选择。
* 这个参数可以是下列值之一:
* @arg TIM_ICPolarity_Rising//上升沿
* @arg TIM_ICPolarity_Falling//下降沿
* @param ICFilter : 指定滤波器的值。
* 取值范围必须在0x0到0xF之间。
* @retval None
*/
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter)
TIM_ETRClockMode1Config函数:
/**
* @brief 选择ETR引脚通过外部时钟1的输入作为时钟
* @param TIMx: 选择要配置的定时器,其中x可以是1、2、3、4、5、9、12或15来。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_ExtTRGPrescaler: 外部触发预分频器。
* 该参数可以是下列值之一:
* @arg TIM_ExtTRGPSC_OFF: 不分频。
* @arg TIM_ExtTRGPSC_DIV2: 二分频。
* @arg TIM_ExtTRGPSC_DIV4: 四分频。
* @arg TIM_ExtTRGPSC_DIV8: 八分频。
* @param TIM_ExtTRGPolarity: 选择外部触发极性。
* 此参数可以是下列值之一:
* @arg TIM_ExtTRGPolarity_Inverted: 低电平或下降沿有效。
* @arg TIM_ExtTRGPolarity_NonInverted: 高电平或上升沿有效。
* @param ExtTRGFilter: 指定滤波器的值。
* 取值范围必须在0x0到0xF之间。
* @retval None
*/
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter)
TIM_ETRClockMode2Config函数:
/**
* @brief 选择ETR引脚通过外部时钟2的输入作为时钟
* @param TIMx: 选择要配置的定时器,其中x可以是1、2、3、4、5、9、12或15来。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_ExtTRGPrescaler: 外部触发预分频器。
* 该参数可以是下列值之一:
* @arg TIM_ExtTRGPSC_OFF: 不分频。
* @arg TIM_ExtTRGPSC_DIV2: 二分频。
* @arg TIM_ExtTRGPSC_DIV4: 四分频。
* @arg TIM_ExtTRGPSC_DIV8: 八分频。
* @param TIM_ExtTRGPolarity: 选择外部触发极性。
* 此参数可以是下列值之一:
* @arg TIM_ExtTRGPolarity_Inverted: 低电平或下降沿有效。
* @arg TIM_ExtTRGPolarity_NonInverted: 高电平或上升沿有效。
* @param ExtTRGFilter: 指定滤波器的值。
* 取值范围必须在0x0到0xF之间。
* @retval None
*/
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)
ETR引脚详见这里
配置时钟输入为外部模式2ETR输入:
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);//选择外部时钟模式2,时钟从TIM_ETR引脚输入
2.1:配置GPIO(当选择外部时钟模式2,外部时钟模式1中的一些时钟输入时)
GPIO_InitTypeDef GPIO_InitStruct;//GPIO初始化结构体
GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;//将引脚模式配置为上拉输入
GPIO_InitStruct.GPIO_Pin=GPIO_Pin_0;//配置Pin0口
GPIO_InitStruct.GPIO_Speed=GPIO_Speed_50MHz;//设置Pin0口的最大翻转速度为50Mhz(输入模式此项不起作用)
GPIO_Init(GPIOA,&GPIO_InitStruct);//配置PA0口
作外部时钟输入时引脚应配置的模式见下图:
三:初始化时基单元:
TIM_TimeBaseInit函数:
/**
* @brief 初始化TIMx时基单元外设
* 使用TIM_TimeBaseInitStruct中指定的参数。
* @param TIMx: 选择要配置的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_TimeBaseInitStruct: 指向TIM_TimeBaseInitTypeDef的指针
* @retval None
*/
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
TIM_TimeBaseInitTypeDef结构体:
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision ; //时钟分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode ; //计数器模式
TIM_TimeBaseInitStructure.TIM_Period ; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler ; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter ; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
成员 | 可选参数 |
---|---|
TIM_ClockDivision | TIM_CKD_DIV1//不分频 |
TIM_CKD_DIV2//2分频 | |
TIM_CKD_DIV4//4分频 | |
TIM_CounterMode | TIM_CounterMode_Up//向上计数模式 |
TIM_CounterMode_Down//向下计数模式 | |
TIM_CounterMode_CenterAligned1//中央对齐模式1 | |
TIM_CounterMode_CenterAligned2//中央对齐模式2 | |
TIM_CounterMode_CenterAligned3//中央对齐模式3 | |
TIM_Period | 0至65535 |
TIM_Prescaler | 0至65535 |
TIM_RepetitionCounter |
TIM_Period(ARR) 和TIM_Prescaler(PSC) 值的计算:计数器溢出频率=CK_PSC / (PSC + 1) / (ARR + 1)
初始化TIM2的时基单元:
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; //定义结构体变量
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频,选择不分频,此参数用于配置滤波器时钟,不影响时基单元功能
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数器模式,选择向上计数
TIM_TimeBaseInitStructure.TIM_Period = 10 - 1; //计数周期,即ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1; //预分频器,即PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; //重复计数器,高级定时器才会用到
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //将结构体变量交给TIM_TimeBaseInit,配置TIM2的时基单元
TIM_ClearFlag(TIM2, TIM_FLAG_Update); //清除定时器更新标志位
//TIM_TimeBaseInit函数末尾,手动产生了更新事件
//若不清除此标志位,则开启中断后,会立刻进入一次中断
//如果不介意此问题,则不清除此标志位也可
四:开启定时器更新中断:
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //开启TIM2的更新中断
五:配置NVIC:
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置NVIC为分组2
NVIC_InitTypeDef NVIC_InitStructure; //定义结构体变量
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; //选择配置NVIC的TIM2线
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //指定NVIC线路使能
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; //指定NVIC线路的抢占优先级为2
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; //指定NVIC线路的响应优先级为1
NVIC_Init(&NVIC_InitStructure); //将结构体变量交给NVIC_Init,配置NVIC外设
六:开启定时器:
TIM_Cmd函数:
/**
* @brief 启用或禁用指定的定时器。
* @param TIMx: 选择要配置的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param NewState: 指定定时器的新状态。
* 该参数包括:ENABLE 或DISABLE。
* @retval None
*/
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
开启TIM2:
TIM_Cmd(TIM2, ENABLE);
中断服务函数:
在STM32中,中断服务函数的函数名是指定的,以下是TIM的中断服务函数函数名:
函数名 | 对应定时器 |
---|---|
TIM2_IRQHandler | TIM2 |
TIM3_IRQHandler | TIM3 |
TIM4_IRQHandler | TIM4 |
标志位读取函数:
TIM_GetFlagStatus函数:
/**
* @brief 检查是否设置了指定的定时器中断标志位。
* @param TIMx: 选择要查询的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_FLAG: 指定要检查的标志位。
* 这个参数可以是下列值之一:
* @arg TIM_FLAG_Update: TIM 更新标志位
* @arg TIM_FLAG_CC1: TIM 捕获/比较 1 标志位
* @arg TIM_FLAG_CC2: TIM 捕获/比较 2 标志位
* @arg TIM_FLAG_CC3: TIM 捕获/比较 3 标志位
* @arg TIM_FLAG_CC4: TIM 捕获/比较 4 标志位
* @arg TIM_FLAG_COM: TIM Commutation Flag
* @arg TIM_FLAG_Trigger: TIM 触发标志位
* @arg TIM_FLAG_Break: TIM Break Flag
* @arg TIM_FLAG_CC1OF: TIM 捕获/比较 1 溢出标志位
* @arg TIM_FLAG_CC2OF: TIM 捕获/比较 2 溢出标志位
* @arg TIM_FLAG_CC3OF: TIM 捕获/比较 3 溢出标志位
* @arg TIM_FLAG_CC4OF: TIM 捕获/比较 4 溢出标志位
* @note
* - TIM6和TIM7只有一个更新标志。
* - TIM9, TIM12和TIM15只能有TIM_FLAG_Update, TIM_FLAG_CC1,
* TIM_FLAG_CC2或TIM_FLAG_Trigger。
* - TIM10, TIM11, TIM13, TIM14, TIM16 和 TIM17 可以有 TIM_FLAG_Update 或 TIM_FLAG_CC1.
* - TIM_FLAG_Break 只用于 TIM1, TIM8 and TIM15.
* - TIM_FLAG_COM 只用于 TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval 指定的标志位的最新状态(SET 或者 RESET)
*/
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
TIM_ ClearFlag函数:
/**
* @brief 清除TIMx的挂起标志。
* @param TIMx: 选择要清除的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_FLAG: 指定要清除的标志位。
* 这个参数可以是下列值的任意组合:
* @arg TIM_FLAG_Update: TIM 更新标志位
* @arg TIM_FLAG_CC1: TIM 捕获/比较 1 标志位
* @arg TIM_FLAG_CC2: TIM 捕获/比较 2 标志位
* @arg TIM_FLAG_CC3: TIM 捕获/比较 3 标志位
* @arg TIM_FLAG_CC4: TIM 捕获/比较 4 标志位
* @arg TIM_FLAG_COM: TIM Commutation Flag
* @arg TIM_FLAG_Trigger: TIM 触发标志位
* @arg TIM_FLAG_Break: TIM Break Flag
* @arg TIM_FLAG_CC1OF: 捕获/比较 1 溢出标志位
* @arg TIM_FLAG_CC2OF: 捕获/比较 2 溢出标志位
* @arg TIM_FLAG_CC3OF: 捕获/比较 3 溢出标志位
* @arg TIM_FLAG_CC4OF: 捕获/比较 4 溢出标志位
* @note
* - TIM6和TIM7只有一个更新标志。
* - TIM9, TIM12 和 TIM15 只有 TIM_FLAG_Update, TIM_FLAG_CC1,
* TIM_FLAG_CC2 或 TIM_FLAG_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 和 TIM17 可以有 TIM_FLAG_Update 或 TIM_FLAG_CC1.
* - TIM_FLAG_Break 仅用于 TIM1, TIM8 和 TIM15.
* - TIM_FLAG_COM 仅用于 TIM1, TIM8, TIM15, TIM16 和 TIM17.
* @retval None
*/
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
TIM_GetITStatus函数:
/**
* @brief 检查TIM中断是否发生。
* @param TIMx: 选择要检查的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_IT: 指定要检查的TIM中断源。
* 这个参数可以是下列值之一:
* @arg TIM_IT_Update: TIM 更新中断
* @arg TIM_IT_CC1: TIM 捕获/比较 1 中断
* @arg TIM_IT_CC2: TIM 捕获/比较 2 中断
* @arg TIM_IT_CC3: TIM 捕获/比较 3 中断
* @arg TIM_IT_CC4: TIM 捕获/比较 4 中断
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM 触发中断
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 只有一个更新中断。
* - TIM9, TIM12 和 TIM15 只有 TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 或 TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 和 TIM17 有 TIM_IT_Update 或 TIM_IT_CC1.
* - TIM_IT_Break 仅用于 TIM1, TIM8 and TIM15.
* - TIM_IT_COM 仅用于 TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval 指定的标志位(TIM_IT)的最新状态(SET or RESET).
*/
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
TIM_ClearITPendingBit函数:
/**
* @brief 清除TIMx的中断挂起位。
* @param TIMx: 选择要清除的TIMx,其中x可以是1到17。(STM32c8t6仅能选择1,2,3,4)
* @param TIM_IT: 指定要清除的中断挂起位。
* 这个参数可以是下列值的任意组合:
* @arg TIM_IT_Update: TIM 更新中断
* @arg TIM_IT_CC1: TIM 捕获/比较 1 中断
* @arg TIM_IT_CC2: TIM 捕获/比较 2 中断
* @arg TIM_IT_CC3: TIM 捕获/比较 3 中断
* @arg TIM_IT_CC4: TIM 捕获/比较 4 中断
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM 触发中断
* @arg TIM_IT_Break: TIM Break Interrupt source
* @note
* - TIM6 and TIM7 只有一个更新中断。
* - TIM9, TIM12 和 TIM15 只有 TIM_IT_Update, TIM_IT_CC1,
* TIM_IT_CC2 或 TIM_IT_Trigger.
* - TIM10, TIM11, TIM13, TIM14, TIM16 和 TIM17 有 TIM_IT_Update 或 TIM_IT_CC1.
* - TIM_IT_Break 仅用于 TIM1, TIM8 and TIM15.
* - TIM_IT_COM 仅用于 TIM1, TIM8, TIM15, TIM16 and TIM17.
* @retval None
*/
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
中断服务函数模板:
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
//要进行的操作
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}