在stm32的开发中我们经常会用到定时器,因此在学习stm32的过程中定时器是必须要学的,而定时主要又分为三大类分别为:
高级控制定时器(TIM1与TIM8)
通用定时器(TIM2~TIM5)
基本定时器(TIM6与TIM7)
今天我只要想给大家介绍的是第二种通用定时器(TIM2~TIM5),还是老样子我先以文字给大家简单概述,在通过视频详细为大家分析细节。
精通定时间的老油条勿喷!!!
首先我们先来了解一下TIM2~TIM5定时器基本功能
(1)16位向上、向下、向上/向下自动装载计数器
(2)16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
(3)4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
(4)使用外部信号控制定时器和定时器互连的同步电路
(5)如下事件发生时产生中断/DMA:
─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
─ 支持针对定位的增量(正交)编码器和霍尔传感器电路
─ 触发输入作为外部时钟或者按周期的电流管理
然后在带大家看一下通用定时器(TIM2~TIM5)通道对应的引脚
上面的定时器对应的引脚只能说是一般情况下是这样的,如果考虑定时器复用功能重映射的话,则会有些出入,在《参考手册》中列出了一些定时器重映射的引脚,如下面几张图片所示:
最后我们来给大家来通过实际配置来举例
在配置之前我们首先要了解通用定时器的时钟可来自于外部或内部,选用默认即是采用内部的。通用定时器的时钟来源为APB1总线,所以首先,得将APB1外设时钟打开。
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
其次,就是定时器的相关参数信息的配置,这些参数信息都在TIM_TimeBaseInitTypeDef这么一个结构体当中,所以得定义这么一个结构体变量。结构体中的有关成员含义如下:
TIM_TimeBaseInitStrcture.TIM_Prescaler = 0x1c20; //时钟预分频系数,看单词意思就知道了,即是将APB1时钟进行相应分频得到一个合适的频率
TIM_TimeBaseInitStrcture.TIM_CounterMode = TIM_CounterMode_Up; //计数模式
TIM_TimeBaseInitStrcture.TIM_Period = 0x270f; //计数周期,即是往ARR寄存器中填的一个自动转载值,这个值等于目标值-1
TIM_TimeBaseInitStrcture.TIM_ClockDivision=TIM_CKD_DIV1; //这是数字滤波器的相关设置,定时的时候不用外部时钟,所以这个设为0即可,TIM_CKD_DIV1这个就是等价于0,你要是设为其他值也不影
下面自然是初始化这个结构体当中的参数信息了。
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStrcture);
再次,就是定时器中断的相关配置了,在配置中断的时候特别一定要注意顺序,否则就会出问题,我一开始就是没注意这个顺序问题,看着错误还不知道怎么回事,还好后面被我发现,哈哈。在使能中断之前一定得先清掉中断中断标志位和中断挂起位,如下:
TIM_ClearFlag(TIM2, TIM_FLAG_Update);
TIM_ClearITPendingBit(TIM2, TIM_FLAG_Update);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
如果不先清掉挂起位和标志位,那么一使能中断,就立马进入中断服务函数,显然这不是我们想要的,我就被这个问题整了一下。接下来就是使能定时器了,TIM_Cmd(TIM2, ENABLE);这自不用说。
最后,就是配置NVIC嵌套向量中断控制寄存器了。
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x00);//the second parameter must be a multiple of 0x200
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//2 bits for pre-emption priority, 2 bits for subpriority
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
其实,我认为在主函数里调用定时器配置函数和NVIC配置函数时,应该先调用NVIC配置函数,因为先设置好中断分组等相关参数信息后,再去打开定时器,定时器中断就能按照NVIC的信息去工作。
接下来的就是在stm32f10x_it.c中写自己的中断服务函数了。
void TIM2_IRQHandler(void)
{
…………
}
到此,通用定时器配置成功。