1.通用定时器工作过程:
2.时钟选择:
- 内部时钟(CK_INT);
- 外部时钟模式1:外部输入脚(TIx);
- 外部时钟模式2:外部触发输入(ETR);
- 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,例如可以配置一个定时器Timer1而作为一个定时器Timer2的预分频器;
3.内部时钟选择:
4.时钟计算方法:
5.计数器模式:
(1)通用定时器可以向上计数、向下计数、向上向下双向计数模式:
①向上计数模式:
计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件;
②向下计数模式:
计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件;
③中央对齐模式(向上/向下计数):
计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件,然后0再从0开始重新计数。
(2)向下计数模式(时钟分频因子=1):
(3)向上计数模式(时钟分频因子=1):
(4)中央对齐计数模式(时钟分频因子=1 ARR=6):
6.定时器中断相关寄存器:
- 计数器当前值寄存器:TIMx_CNT;
- 预分频寄存器:TIMx_PSC;
- 自动重装载寄存器:TIMx_ARR;
- 控制寄存器1:TIMx_CR1;
- DMA中断使能寄存器:TIMx_DIER;
7.常用库函数:
- 定时器参数初始化:void TIM_TimeBaseInit(TIM_TypeDef* TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
- 定时器使能:void TIM_Cmd(TIM_TypeDef* TIMx,FunctionalState NewState);
- 定时器中断使能函数:void TIM_ITConfig(TIM_TypeDef* TIMx,uint16_t TIM_IT,FunctionalState NewState);
- 状态标志位获取和清除: ①FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx,uint16_t TIM_FLAG); ②void TIM_ClearFlag(TIM_TypeDef* TIMx,uint16_t TIM_FLAG); ③ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx,uint16_t TIM_IT); ④void TIM_ClearITPendingBit(TIM_TypeDef* TIMx,uint16_t TIM_IT);
8.定时器中断实现步骤:
- 使能定时器时钟:RCC_APB1PeriphClockCmd();
- 初始化定时器,配置ARR,PSC寄存器:TIM_TimeBaseInit();
- 开启定时器中断,配置NVIC:void TIM_ITConfig(); NVIC_Init();
- 使能定时器:TIM_Cmd();
- 编写中断服务函数:TIMx_IRQHandler();
9.定时器中断试验:
通过定时器中断配置,每隔500ms中断一次,然后中断服务函数中控制LED实现LED1的闪烁;
(1)主函数:
#include "delay.h"
#include "led.h"
#include "timer.h"
/*
溢出时间计算:
①Tout(溢出时间)=(ARR+1)(PSC+1)/TCLK;
②TCLK:系统时钟(72MHz)
③72MHz/(7199+1)=10KHz
④1/10KHz=0.1ms
⑤0.1ms*(4999+1)=500ms
*/
int main(){
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置中断优先级分组->2组
delay_init(); //延时初始化
LED_Init(); //LED初始化
TIME3_Init(4999,7199); //定时器3中断初始化
while(1){
LED0=!LED0;
}
}
(2)头文件:
#ifndef __TIMER_H
#define __TIMER_H
typedef unsigned short u16;
void TIME3_Init(u16 arr,u16 psc); //定时器3初始化
#endif
(3)定时器中断功能函数:
#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "timer.h"
/*
功能:定时器3中断初始化
变量:arr:自动重装载值计数周期值 psc:分频系数
返回值:无
*/
void TIME3_Init(u16 arr,u16 psc)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
NVIC_InitTypeDef NVIC_InitStruct;
//1.使能定时器3时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
//2.初始化定时器3
TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1; //设置时钟分频因子->这里选择1分频
TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up; //设置计数模式->这里选择向上计数
TIM_TimeBaseInitStruct.TIM_Period=arr; //设置自动重装载计数周期值
TIM_TimeBaseInitStruct.TIM_Prescaler=psc; //设置分频系数
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
//3.开启定时器中断
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //设置定时器3为更新中断
//4.中断服务管理
NVIC_InitStruct.NVIC_IRQChannel=TIM3_IRQn; //设置中断通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2; //抢占优先级
NVIC_InitStruct.NVIC_IRQChannelSubPriority=3; //子优先级
NVIC_Init(&NVIC_InitStruct);
//5.使能定时器
TIM_Cmd(TIM3,ENABLE);
}
/*
功能:定时器3中断服务函数
变量:无
返回值:无
*/
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET) //判断定时器3的中断是否是更新中断->这里指是
{
LED1=!LED1; //LED1闪烁
TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位
}
}