该文章是记录我学习stm32定时器的过程,若有不正确的地方请多指正,万分感谢!!!!
TIM简单介绍
类型 | 编号 | 总线 | 功能 |
高级定时器 | TIM1,TIM8 | APB2 | 拥有通用定时器全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 |
通用定时器 | TIM2,TIM3, TIM4,TIM5 | APB1 | 拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 |
基本定时器 | TIM6,TIM7 | APB1 | 拥有定时中断、主模式触发DAC的功能 |
基本定时器
主要功能
框图分析
基本定时器的时钟源只能选择内部时钟作为时钟源,内部时钟源经过控制器到达预分频器(PSC)经过分频后传递给计数器(CNT),由计数器对经过分频后的内部时钟进行计数,并与自动重装寄存器(ARR)中的数值进行比较,当数值与自动重装寄存器中的数值相等的时候就会将计数器清零并产生中断信号和更新事件,中断事件经过主模式触发控制器映射到TRGO的位置并由TRGO接到DAC转换引脚上。主模式触发的更新事件不需要软件的参与,由硬件自动完成。
通用定时器
主要功能
框图分析
首先时钟源的来源比基本定时器更加丰富,有内部时钟源,TIM_ETR引脚输入的信号作为时钟源,ITR0~ITR3来自其他时钟的定时器信号作为时钟源(定时器的主模式输出TRGO可以将定时器的信号传输给另外一个定时器)见下表,此外还可以是来自引脚TIMx_CH_1(TI1F_ED或TI1FP1传输到控制器)和TIMx_CH_2(TI2FP2传输到控制器).
其次,时基单元部分与基本定时器相比较有(向下计数,向上计数,中央对齐计数模式).
最后,有关输入捕获和输出捕获寄存器是和PWM有关,可以参照后续文章。
高级定时器
主要功能
![](https://i-blog.csdnimg.cn/direct/6c2fad3b9c60453da8cae03cc54030f6.png)
使用定时器计数的初始化一般步骤
1.定时器时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
2.选择一个定时器的时钟源是内部时钟(以TIM2选择内部时钟源为例)
TIM_InternalClockConfig(TIM2);
3.时基单元的初始化以及中断的使能
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1)
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_ClearITPendingBit(TIM2,TIM_IT_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
注意:由于我们的预分频器的值要起作用必须是在更新事件发生以后, TIM_TimeBaseInit函数中使用软件中断来产生了一个更新事件然后进入中断函数,使用我们要走初始化函数后面加一个清除中断标志位的函数防止设置初始化造成的中断函数调用。
4.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=0;
NVIC_Init(&NVIC_InitStructure);
5.启动定时器
TIM_Cmd(TIM2,ENABLE);
最后,每次执行完中断函数以后要清除中断标志位(注意中断函数名在启动文件中的中断向量表里面)。
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
完整初始化代码
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_ClearITPendingBit(TIM2,TIM_IT_Update);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
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=0;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);