TIM定时中断
- TIM简介
- 时基单元
- 定时器类型
- 基本定时器
- 主模式触发DAC
- 通用计时器
- 输入
- 定时器级联
- 高级计时器
- 定时中断基本结构
- 预分频器时序
- 计数器时序
- 计数器预装时序
- 无预装时序
- 有预装时序
- RCC时钟树
- 代码—定时器定时中断
- 代码—定时器外部中断
TIM简介
- TIM(Timer计时器)
- 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
- 16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时
- 不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
- 根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
时基单元
计数器:用于执行计数定时的一个寄存器,每接收一次时钟信号,计数器加一
预分频器:对计数器的时钟进行分频,使计数更加灵活,原理是预分频器可以对时钟脉冲进行整合,将多个脉冲整合为一个脉冲输出给计数器
自动重装寄存器:用于设置申请中断值
- 定时器中断时间最大值=1/(72Mhz/65535/65535)=59.65s
定时器类型
- STM32F103C8T6定时器资源:TIM1,TIM2,TIM3,TIM4
基本定时器
预分频器:对输入的频率提前进行分频操作,输出频率 = 输入频率 / 分频系数,预分频器值 = 分频系数 - 1,最大预分频器值为65535 + 1 = 65536
计数器:对预分频后的计数时钟进行计数,每出现一个上升沿,计数器值加一,最大计数值65535
自动重装载寄存器:存储设定的计数目标值,当计数器计数到目标值时,产生中断信号,并且清零计数器,计数器自动开启下一次计时
主模式触发DAC
为了每隔一段时间触发DAC,可以通过主模式将事件更新映射到TRGO后触发DAC
通用计时器
支持向下计数模式,即为从重装值开始,向下自减,到0之后申请中断并返回重装值循环
支持中央对齐模式模式,即为从重装值开始,先向上自增到重装值并申请中断,然后向下自减到0后,再申请中断,依次循环
编码器接口可读取正交编码器波形,可通过TRGO映射
输入
- 可选的外部时钟(TIMx_ETR)
- ITRx(其他定时器)
- TIMx_CH1引脚边沿
- CH1引脚(T12FP1),CH2引脚(T12FP2)
定时器级联
可通或TIMx的事件更新映射到TRGO,内部触发连接输出到其他定时器,实现定时器级联
- ITR与定时器的连接关系
高级计时器
- 重复次数计数器:可配置周期进行事件更新与事件中断
- DTG(Dead Time Generate)死区生成电路,用于防止直通
- 输出互补,可输出一对互补的PWM波形
- 刹车输入:产生故障可自动切断输出
定时中断基本结构
中断输出控制中断输出的允许位
预分频器时序
计数器寄存器中的FC:ARR自动重装值标志位
预分频缓冲器(影子寄存器):当进行分频值改变操作时,会等到当前计数周期完成后才产生改变
计数器时序
CNT_EN:计数器使能,高电平启动
更新中断标志位(UIF):置 1 申请中断,需要在中断程序中手动清零
计数器预装时序
- 通过设置ARPE位进行配置
无预装时序
计数到最新设定的指定值(自动加载寄存器值)后直接更新开始下一轮计数
有预装时序
受影子寄存器作用,重装值在更改后不会立即生效,而是在计数器计数到旧重装值后的下一个周期才生效。
RCC时钟树
- 四个振荡源:内部8Mhz高速RC振荡器,外部4-16Mhz高数石英晶体振荡器,外部32.768Khz低速晶振(供RTC时钟使用),内部40Khz低速RC振荡器(看门狗时钟)
- ST配置: 先启动内部8Mhz内部时钟,接着外部时钟通过锁相环(PLLMUL)进行倍频到指定频率,最后设定该频率为系统频率
- 时钟安全系统(CSS) :监测外部时钟状态,如果失效,切换为内部时钟
代码—定时器定时中断
- 函数
TIM_DeInit(TIM_TypeDef*TIMx);//恢复缺省配置/*时基单元*/TIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);//时基单元初始化TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct);//结构体变量赋默认值/*运行控制*/TIM_Cmd(TIM_TypeDef*TIMx,FunctionalState NewState);//计数器使能/*中断输出控制*/TIM_ITConfig(TIM_TypeDef*TIMx,uint16_tTIM_IT,FunctionalState NewState);//使能中断输出信号(中断输出控制)/*时钟源选择*/TIM_InternalClockConfig(TIM_TypeDef*TIMx);//内部时钟选择TIM_ITRxExternalClockConfig(TIM_TypeDef*TIMx,uint16_tTIM_InputTriggerSource);//选择ITRx其他定时器时钟TIM_TIxExternalClockConfig(TIM_TypeDef*TIMx,uint16_tTIM_TIxExternalCLKSource,uint16_tTIM_ICPolarity,uint16_tICFilter);//选择TIx捕获通道时钟,TIM_TIxExternalCLKSource(选择TIx具体引脚),TIM_ICPolarity(选择级性),ICFilter(选择滤波器)TIM_ETRClockMode1Config(TIM_TypeDef*TIMx,uint16_tTIM_ExtTRGPrescaler,uint16_tTIM_ExtTRGPolarity,uint16_tExtTRGFilter);//选择ETR通过外部模式1输入的时钟,TIM_ExtTRGPrescaler(外部触发预分频器),极性,滤波器TIM_ETRClockMode2Config(TIM_TypeDef*TIMx,uint16_tTIM_ExtTRGPrescaler,uint16_tTIM_ExtTRGPolarity,uint16_tExtTRGFilter);//选择ETR通过外部模式2输入的时钟,同上TIM_ETRConfig(TIM_TypeDef*TIMx,uint16_tTIM_ExtTRGPrescaler,uint16_tTIM_ExtTRGPolarity,uint16_tExtTRGFilter);//配置ETR引脚的预分频器,极性,滤波器参数/*其他配置*/TIM_PrescalerConfig(TIM_TypeDef*TIMx,uint16_tPrescaler,uint16_tTIM_PSCReloadMode);//预分频值配置TIM_CounterModeConfig(TIM_TypeDef*TIMx,uint16_tTIM_CounterMode);//计数器计数模式配置TIM_ARRPreloadConfig(TIM_TypeDef*TIMx,FunctionalState NewState);//自动重装器预装功能配置TIM_SetCounter(TIM_TypeDef*TIMx,uint16_tCounter);//计数器写入计数值TIM_SetAutoreload(TIM_TypeDef*TIMx,uint16_tAutoreload);//自动重装器写值TIM_GetCounter(TIM_TypeDef*TIMx);//获取当前计数器的值TIM_GetPrescaler(TIM_TypeDef*TIMx);//获取当前预分频器值- TIMER.c
#include"stm32f10x.h"// Device headervoidTIMER_Init(void){/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);/*选择内部时钟*/TIM_InternalClockConfig(TIM2);/*配置时基单元*/TIM_TimeBaseInitTypeDef TIM_TimerBaseInitStructure;TIM_TimerBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频TIM_TimerBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//设置计数模式为向上计数TIM_TimerBaseInitStructure.TIM_Period=10000-1;//ARR自动重装器值TIM_TimerBaseInitStructure.TIM_Prescaler=7200-1;//PSC预分频器值,定时频率 = 72M/(PSC + 1)/(ARR + 1)TIM_TimerBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器值,用于高级计数器TIM_TimeBaseInit(TIM2,&TIM_TimerBaseInitStructure);/*使能中断*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手动清除更新中断标志位,避免刚初始化完就进中断TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*NVIC配置*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//NVIC通道选择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){ //获取中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位 } } */- main.c
#include"stm32f10x.h"// Device header#include"TIMER.h"uint16_tNum;intmain(void){/*模块初始化*/TIMER_Init();while(1){}}voidTIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//获取中断标志位Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位}}代码—定时器外部中断
- TIMER.c
#include"stm32f10x.h"// Device headervoidTIMER_Init(void){/*开启时钟*/RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//启动GPIOA时钟/*配置GPIO*/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,0x00);//ETR外部时钟模式2配置/*配置时基单元*/TIM_TimeBaseInitTypeDef TIM_TimerBaseInitStructure;TIM_TimerBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;//指定时钟分频TIM_TimerBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//设置计数模式为向上计数TIM_TimerBaseInitStructure.TIM_Period=10-1;//ARR自动重装器值TIM_TimerBaseInitStructure.TIM_Prescaler=1-1;//PSC预分频器值,定时频率 = 72M/(PSC + 1)/(ARR + 1)TIM_TimerBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器值,用于高级计数器TIM_TimeBaseInit(TIM2,&TIM_TimerBaseInitStructure);/*使能中断*/TIM_ClearFlag(TIM2,TIM_FLAG_Update);//手动清除更新中断标志位,避免刚初始化完就进中断TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);/*NVIC配置*/NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;//NVIC通道选择NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;//开启通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;//响应优先级NVIC_Init(&NVIC_InitStructure);/*启动定时器*/TIM_Cmd(TIM2,ENABLE);}uint16_tTimer_GetCounter(void){returnTIM_GetCounter(TIM2);}/* void TIM2_IRQHandler(void){ if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){ //获取中断标志位 TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //清除中断标志位 } } */- main.c
#include"stm32f10x.h"// Device header#include"TIMER.h"uint16_tNum;intmain(void){/*模块初始化*/TIMER_Init();while(1){}}voidTIM2_IRQHandler(void){if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//获取中断标志位Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位}}