定时器离不开中断,前置技能——中断若没有加点的话,可以去下面的链接看下
传送门:https://blog.csdn.net/pmj110119/article/details/86748016
STM32F1的通用 TIMx
(TIM2、TIM3、TIM4 和 TIM5)定时器功能包括:
16位自动装载计数器(TIMx_CNT)
16位可编程预分频器(TIMx_PSC),分频系数为1~65535之间任意数值。
4个独立通道(TIMx_CH1~4),这些通道可以用来作为:
A. 输入捕获
B. 输出比较
C. PWM生成
D. 单脉冲模式输出
可使用外部信号(TIMx_ETR)控制定时器与定时器互连(用1个定时器控制另外一个定时器)的同步电路
如下事件发生时产生中断/DMA:
A. 更新:计数器溢出,计数器初始化
B. 触发事件:计数器启动、停止、初始化
C. 输入捕获
D. 输出比较
E. 增量编码器和霍尔传感器电路
F. 触发输入作为外部时钟或者按周期的电流管理
TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的使能使能函数来使能 TIM3。调用的函数是:
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
参数结构体类型为 TIM_TimeBaseInitTypeDef,
初始化函数为 TIM_TimeBaseInit
, 范例如下:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 5000; //设置重载计数周期值:5000
TIM_TimeBaseStructure.TIM_Prescaler =7199; //设置分频系数:7199
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //时钟分频因子:时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //设置计数方式:向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //初始化TIM3
接下来进行定时器中断使能,通过 TIM_ITConfig
函数实现
第一个参数是选择定时器号,取值 TIM1~TIM17.
第二个参数指明定时器中断的类型。包括更新中断 TIM_IT_Update
,触发中断 TIM_IT_Trigger
,以及输入捕获中断等等
(本章代码都以更新中断为例)
第三个参数填 ENABLE就好
例如使能TIM3的更新中断,格式为:
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
不加赘述,直接贴代码
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //初始化 NVIC 寄存器
配置好定时器后,就可以开启定时器了。通过 TIM_Cmd
函数使能定时器
TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外设
这个函数很简单,一看便懂。
定时器中断产生后,需要通过中断服务函数来处理这次中断。
首先,判断定时器是否发生更新(溢出)中断,方法为
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
在这个 if 里面进行这次中断的处理。
中断处理函数结束前,需要清除中断标志位,函数调用格式如下
TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
首先申明几个参数:arr
为自动重装值;psc
为时钟预分频数 ,这两个由我们用户指定
Tclk
为 TIM 的输入时钟频率(TIM3为72 Mhz)
溢出时间计算公式为:Tout= ((arr+1)*(psc+1))/Tclk
指定 arr
=4999;psc
=7199
则 Tout
= ((4999+1)*( 7199+1))/72=500000us=500ms。
可写为 timer.c文件,直接调用
#include "timer.h"
#include "led.h"
//通用定时器 3 中断初始化
//这里时钟选择为 APB1 的 2 倍,而 APB1 为 36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器 3!
void TIM3_Int_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①时钟 TIM3 使能
//定时器 TIM3 初始化
TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值
TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //②初始化 TIM3
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //③允许更新中断
//中断优先级 NVIC 设置
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
NVIC_Init(&NVIC_InitStructure); //④初始化 NVIC 寄存器
//⑤使能 TIM3
TIM_Cmd(TIM3, ENABLE);
}
//定时器 3 中断服务程序⑥
void TIM3_IRQHandler(void) //TIM3 中断
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志
LED1=!LED1; //本次中断执行的代码
}
}