1.TIM简介
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
分为高级定时器、通用定时器、基本定时器三种
类型 | 编号 | 总线 | 功能 |
高级定时器 | TIM1、TIM8 | APB2 | 拥有通用定时器的全部功能,并额外具有重复计数器、死区生成、互补输出、刹车输入等功能 |
通用定时器 | TIM2、TIM3、TIM4、TIM5 | APB1 | 拥有基本定时器全部功能,并额外具有内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等功能 |
基本定时器 | TIM6、TIM7 | APB1 | 拥有定时中断、主模式触发ADC的功能 |
2.基本定时器
预分频器PSC:若该寄存器写0,则为1分频,主频/2;若写1,则为2分频,主频/2...最大可以写65535,则为65536分频
计数器CNT:计数时钟每来一个上升沿,计数器+1,里面的值可以从0加到65535,再加就回到0
自动重装寄存器:存的是计数的目标,在计数过程中,当计数值等于该值时,就会产生一个中断信号(一般叫做更新中断),并且清零计数器
3.通用定时器
通用定时器和高级定时器拥有向上计数、向下计数和中央对齐计数三种方式
向上计数:计数值从0向上计数到自动重装值产生中断并且清零
向下计数:计数值从自动重装值开始向下递减到0产生中断并重回自动重装值
中央对齐:计数器从0计数到自动重装值产生中断再向下递减到0产生中断
4.高级定时器
重复计数器:可以实现每隔几个计数周期再触发中断,最大值为65535+1
5.定时中断基本结构
6.预分频器时序
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
7.计数器时序
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)
计算溢出时间则取倒数
更新中断标志置1则产生中断,需要在中断程序中手动清零
8.标准库相关代码介绍
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//时基单元初始化
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//把结构体变量赋初始值
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);
//使能计数器
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);
//使能外设的中断输出
//时钟源选择相关函数
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
//选择RCC内部时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//选择ITRx其他定时器时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
uint16_t TIM_ICPolarity, uint16_t ICFilter);
//选择TIx捕获通道的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
//选择ETR通过外部时钟模式1输入的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler,
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
//选择ETR通过外部时钟模式2输入的时钟
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//单独用来配置ETR引脚的预分频器、极性、滤波器等参数
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
//配置单独要写入的预分频PSC的值
//第三个参数选择该值是立刻生效还是在更新事件后生效
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
//可以用来改变计数器的计数模式
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
//选择有预装还是无预装
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
//给计数器写入一个值
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);
//给自动重装数写入一个值
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
//返回当前计数器的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
//获取当前预分频器的值
//分别在主程序和中断函数里获取标志位和清除标志位的函数
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);
9.案例
9.1定时器定时中断
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIM_InternalClockConfig(TIM2); //选择内部时钟,可以不写,因为上电默认为使用内部时钟
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
//可以选择1分频、2分频、4分频,如消除传感器的抖动
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
//选择计数器模式
TIM_TimeBaseInitStructure.TIM_Period = 10000-1;
//自动重装器ARR的值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200-1;
//预分频器PSC的值
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
//重复计数器的值,高级定时器才有
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_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 = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);
//启动定时器
}
9.2定时器外部时钟
#include "stm32f10x.h" // Device header
void Timer_Init(void)
{
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&GPIO_InitStructure);
TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);
//选择ETR通过外部时钟模式2作为时钟源
//第二个参数选择分频系数,当前为不分频;第三个参数选择外部触发的极性,当前为上升沿有效;第三个参数为滤波器,当前为不使用滤波器
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_Period = 10-1;
TIM_TimeBaseInitStructure.TIM_Prescaler = 1-1;
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
TIM_ClearFlag(TIM2,TIM_FLAG_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 = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2,ENABLE);
}
uint16_t Timer_GetCounter(void)
{
return TIM_GetCounter(TIM2);
//返回计时器CNT的值
}