STM32中的TIM模块简介及TIM中断详解
文章目录
一、TIM简介
对输入的时钟(方波)进行计数
,并在计数值达到设定值
时触发中断
还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
二、定时器类型
注意:STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4
基本定时器
只能连接内部时钟(72MHZ)
主模式触发DAC
:防止主程序频繁被中断,通过主模式,将定时器的更新事件映射到触发输出,定时器的更新就无须通过更新中断来实现【类似于DMA控制器,实现硬件自动化】通用定时器
通用定时器包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
通用定时器和高级定时器支持向上计数,向下技术,中央对齐模式
编码器接口:读取正交编码器的输出波形
该框图可以分为三个部分
上面部分可以完成定时中断功能,内外时钟源选择和主从触发模式选择
下面由输入捕获单元和输出比较电路组成
外部时钟模式2:通过TIMx_ETR——触发控制器——时基单元

外部时钟模式1(用作触发输入):通过TRGI——触发控制器——时基单元

各种定时器时钟源的GPIO配置
高级定时器
三、定时中断基本结构
中断源选择:
GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
如通用定时器框图所示
,一个定时器中包含多个中断源如TGI,计数器值等于重装值,输入捕获与输出比较匹配时,参数可以选择如下
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
@param TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.
* This parameter can be any combination of the following values:
* @arg TIM_IT_Update: TIM update Interrupt source
* @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
* @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
* @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
* @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
* @arg TIM_IT_COM: TIM Commutation Interrupt source
* @arg TIM_IT_Trigger: TIM Trigger Interrupt source
* @arg TIM_IT_Break: TIM Break Interrupt source
四、时序图
预分频器时序
计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)【预分频的值+1=实际的分频系数】
当计数到一半改变分频值,不会从那个时刻修改,而是等本次计数周期结束后才开始【结束会产生更新事件,预分频寄存器的值才会传递到预分频缓冲器,下一个周期才会起作用】
CK_PSC与CK_CNT的关系
预分频寄存器实际上有两个,一个是供用户读写使用的预分频控制寄存器,该寄存器不会决定分配系数,另一个是缓冲寄存器(影子寄存器),真正起作用
计数器时序
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1)
例如:定时1s时间计算psc和arr:
自动重装寄存器有缓冲寄存器可以使用,使用则是有预装,不使用则是无预装,通过设置ARPE位进行设置
计数器无预装时序
计数器有预装时序
RCC时钟树

五、定时器定时中断
Timer.c
#include "stm32f10x.h" // Device header
uint16_t Num;
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;//重装值
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 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;//stm32f10x.h中对应型号的参数
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_Init(&NVIC_InitStructure);
TIM_Cmd(TIM2, ENABLE);//运行控制,使能计数器,让其工作
}
//定时器中断函数
void TIM2_IRQHandler(void)
{
//中断函数中查看标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++;
//中断函数中清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
六、定时器外部时钟
Timer.c
#include "stm32f10x.h" // Device header
uint16_t Num;
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);//PA0可以作为TIMx_ETR信号输入端
TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);//第二个参数是预分频器,第三个参数是外部触发的极性,第一是反向,低电平或下降沿有效,第二个是不反向,高电平或上升沿有效,最后一个参数是外部触发滤波器,通过设置16进制来设定采样频率和采样个数
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);//获取计数器的值
}
void TIM2_IRQHandler(void)
{
//中断函数中查看标志位
if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
{
Num ++;
//中断函数中清除标志位
TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
}
}
七、定时器库函数(tim.h)
void TIM_DeInit(TIM_TypeDef* TIMx);//恢复缺省配置
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);//内部时钟模式
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);//ITx其他定时器模式
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);//单独设置预分频值
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);
参考视频:江科大自化协