00.定时中断的基本结构
上图是定时中断的基本结构,我们要想让定时中断工作,只需要将图中的各个部分都打通即可。
步骤可以概括如下
- 1.开启RCC时钟,时钟打开之后定时器基准时钟和外设工作的时钟也会同时打开。
- 2.选择时基单元的时钟源(内部时钟或外部时钟),对于定时中断就选择内部时钟源
- 3.配置时基单元,主要是配置PSC、ARR、CNT 和上图对应
- 4.使能更新中断,运行更新中断输出到NVIC。
- 5.配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。
- 6.启动定时器。
- 7.定时器更新触发中断。
01.开启RCC时钟
相关API
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//TIM2是APB1总线的外设
注意 这里我们使用TIM2 通用定时器,由于TIM2是APB1的总线时钟外设 则需要使用APB1的开启时钟函数。
02.选择时基单元的时钟源
//2.选择时基单元的时钟
TIM_InternalClockConfig(TIM2);
选择内部时钟,则TIM2的时基单元就由内部时钟来驱动了
03.配置时基单元
相关API
初始化时基单元 TIM_TimeBaseInit
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
此函数为初始化时基单元,参数1 为 选择定时器,参数2 为时基单元配置结构体。
时基单元配置结构体 TIM_TimeBaseInitTypeDef
//3.配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
TIM_TimeBaseInitStruct.TIM_ClockDivision= TIM_CKD_DIV1;//指定时钟分频
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数器模式
//关键寄存器值
/*
* 对72MB进行 7200分频 得到 10k的计数频率,在10k的频率下记10k个数
*为1s
*/
TIM_TimeBaseInitStruct.TIM_Period = 10000-1;//ARR自动重装器的值
TIM_TimeBaseInitStruct.TIM_Prescaler= 7200-1;//PSC预分频器值7200
TIM_TimeBaseInitStruct.TIM_RepetitionCounter= 0;//重复计数器的值高级定时器才用
成员变量说明
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 定时器周期 ARR自动重装器的值
TIM_Prescaler PSC预分频器的值
TIM_RepetitionCounter 重复计数器值 (高级定时器使用)
如果想定时1s的时间那么应该怎么算呢?
定时频率=CK_PSC/(PSC+1)/(ARR+1),CK_PSC为基本时钟源 ,输入预分频器的时钟频率
对基本时钟源72MHz 进行7200分频 得到10k的计数频率,在10k的频率下记10000个数 即1s。
则TIM_Period =1000-1,TIM_Prescaler =7200-1。
04.使能更新中断,运行更新中断输出到NVIC
相关API
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//使能中断,para2 选择中断的类型
参数说明:
参数1 定时器选择
参数2 中断源选择 可选值为TIM_IT_Update,更新中断 TIM_IT_CC1 ,捕获比较通道1,TIM_IT_CC2,捕获比较通道2,TIM_IT_CC3 ,捕获比较通道3,TIM_IT_CC,3 ,捕获比较通道3
TIM_IT_CC4 ,捕获比较通道4,TIM_IT_COM,TIM_IT_Trigger,TIM_IT_Break
参数3 中断使能 可选值 为 ENABLE,DISABLE
05配置NVIC
//NVIC
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//优先级分组
NVIC_InitTypeDef NVIC_InitS ;
NVIC_InitS.NVIC_IRQChannel= TIM2_IRQn;//中断通道
NVIC_InitS.NVIC_IRQChannelCmd= ENABLE;
NVIC_InitS.NVIC_IRQChannelPreemptionPriority= 2;//抢占优先级
NVIC_InitS.NVIC_IRQChannelSubPriority = 1;//响应优先级
NVIC_Init(&NVIC_InitS);//NVIC 初始化
06.启动定时器
//启动定时器
TIM_Cmd(TIM2, ENABLE);
07.定时器更新触发中断
中断函数
void TIM2_IRQHandler (void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)//检查中断标志位
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
说明
TIM_GetITStatus(TIM2,TIM_IT_Update) 获取中断标志位
参数1 为指定定时器
参数2 为中断类型
TIM_ClearITPendingBit(TIM2,TIM_IT_Update) 清除中断标志位
08.定时器外部时钟
对于使用定时器的外部时钟只需要在02.选择时基单元的时钟源时,指定外部时钟配置即可。
相关API
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter);
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter);
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
uint16_t ExtTRGFilter);
以TIM_ETRClockMode2Config 来说明
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
参数1:选择对应的定时器 这里选的TIM2
参数2:外部触发与分频器 TIM_ExtTRGPSC_OFF 不分频 TIM_ExtTRGPSC_DIV2 2分频
TIM_ExtTRGPSC_DIV4 4分频 TIM_ExtTRGPSC_DIV8 8分频
参数3 :外部触发的极性
TIM_ExtTRGPolarity_Inverted 低电平或下降沿有效
TIM_ExtTRGPolarity_NonInverted 高电平或上升沿有效
参数4:外部触发滤波器 不使用配置为 0x00 对应关系见下表
外部触发还需要配置GPIO ,代码如下
//配置GPIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_INITS;
GPIO_INITS.GPIO_Mode=GPIO_Mode_IPU;//配置上拉输入
GPIO_INITS.GPIO_Pin=GPIO_Pin_0;
GPIO_INITS.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_INITS);
TIM_ETRClockMode2Config( TIM2, TIM_ExtTRGPSC_OFF,
TIM_ExtTRGPolarity_NonInverted, 0x00);