TIM(Timer)定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。
16位 计数器、预分频器、自动重装寄存器 的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时。(72/65536/65536=59.65s)
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4
基本定时器:
拥有定时中断、主模式触发DAC的功能
基准时钟->预分频器->计数器
时基单元:预分频器、计数器、自动重装寄存器。
预分频器
如果预分频器写0,不分频,输出频率=输入频率=72MHz
如果预分频器写1,二分频,输出频率=输入频率/2=36MHz
如果预分频器写,三分频,输出频率=输入频率/3=24MHz
最大值可以写65535也就是65536分频,输出频率=72/65536
CNT计数器
对预分频后的始终进行计数,计数时钟每来一个上升沿,计数器的值就加
自动重装寄存器
当计数值等于自动重装值时,代表计时时间到,会产生UI更新中断信号,并且清零计数器。(图中向上箭头:更新中断;更新中断通往NVIC)(图中向下箭头:更新事件,更新事件不触发中断,但是可以触发内部其他电路的工作)
主模式触发DAC的功能
主模式把更新事件映射到 触发输出TRGO的位置,TRGO直接接到DAC的触发转换引脚上,直接触发DAC,不需要软件的参与,实现了硬件的自动化。
通用定时器:
除了向上计数,通用定时器和高级定时器还支持向下计数模式和中央对齐模式
向下计数模式:从重装值开始,向下自减。
中央对齐模式:从0开始,先向上自增,到重装值,申请中断,然后向下自减到0 再次申请中断。
内外时钟源选择:
第一个外部时钟:TIMx_ETR引脚(PA0)上的外部时钟。两个输出:
1.ETRF进入触发控制器,进而到时基单元,这一路也叫外部时钟模式2;
2.TRGI:用作触发输入使用,触发输入和从模式,以后课程讲。这一路叫外部时钟模式1.
ITRx(ITR0~ITR3)信号来来源于其他定时器,主模式的TRGO可以通向其他定时器。
表格意思为:例如:TIM2定时器的ITR0信号来自于上一个时钟(TIM1)
定时器级联功能,比如:先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,然后再初始化TIM2,这里算则ITR2,对应的就是TIM3的TRGO
时钟还能通过CH1获得,ED是边沿的意思,可以是上升沿可以是下降沿。
last :时钟还能通过TI1FP1和TI2FP2获得。
总结:外部时钟模式1的引脚可以是ETR引脚(外部时钟)、(ITR)其他定时器、CH1引脚的边沿、CH1和CH2引脚的TI1FP1和TI2FP2获得
右下角是输出比较电路,共有四个通道,分别对应CH1到CH4的引脚,可以用于输出PWM波形,驱动电机。
左下角是输入捕获电路,也有四个通道。对应的也是CH1到CH4的引脚,可以用于测量输入方波的频率等。
中间是捕获/比较寄存器,是输入捕获和输出比较电路共用的。因为输入捕获和输出比较不能停驶使用,所以寄存器共用,引脚共用。之后再具体分析。
高级定时器:
申请中断的地方加了一个重复次数计数器,可以实现每隔几个计数周期,才发生一次更新事件和更新中断。
DTG(死区生成电路),右侧变为互补输出,可以输出一对互补的PWM波,可以驱动三相无刷电机。
定时中断基本结构图:
中断输出控制(即,中断输出允许位):解决定时器模块有很多地方都要申请中断,看是否需要这个中断,如果需要就允许,如果不需要这个中断,就禁止。(更新会申请中断,触发信号(TRGO)也会申请中断、输入捕获和输出比较匹配时也会申请中断)
时基单元运行细节问题:
预分频时序:
计数器计数频率:CK_CNT= CK_PSC/(PSC + 1)
CK_PSC:预分频器的输入时钟。一般为72Mhz
CNT_EN:计数器使能,高电平计数器正常运行,低电平计数器停止。
CK_CNT:计数器时钟,即时分频器的时钟输出,也是计数器的时钟输入。
一个计时周期结束时,产生了更新事件,预分频(控制)寄存器的值才会被传递到缓冲器里去,才会生效。
计数器时序:
计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR +1)=CK_PSC / (PSC +1) / (ARR +1)
计数器无预装时序:
计数器有预装时序:
RCC时钟树:
上图时钟树详解,6-1 42分钟。
通用定时器和基本定时器接在APB1上
无论什么定时器,内部基准时钟都是72Mhz。
定时中断初始化流程:
1. 开启RCC时钟。
2. 选择时基单元的时钟源,对于定时中断,选择内部时钟源。
3. 配置时基单元,包括预分频器、自动重装寄存器、计数模式等,一个结构体即可配置好。
4. 配置输出中断控制,允许更新中断输出到NVIC。
5.配置NVIC,在NVIC中打开定时器中断通道,并分配一个优先级。
6. 运行控制,使能一下计数器。再写一个定时器中断函数。
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);使能中断输出信号;TIM_IT 选择配置哪个中断输出,NewState使能还是失能。
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);选择内部时钟
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捕获通道的时钟。TIM_TIxExternalCLKSource选择TIx的某个引脚;TIM_ICPolarity输入的极性;ICFilter滤波器。
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);选择ETR通过外部时钟模式1输入的时钟。TIM_ExtTRGPrescaler外部触发预分频器:可以对ETR的外部时钟再提前做一个分频;
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);写预分频值;TIM_PSCReloadMode选择模式:1.听从安排等待更新事件生效,2.在写入后,手动产生一个更新事件,让这个值立即生效。
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);用来改变计数器的计数模式。
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);自动重装器预装功能配置
补充:
滤波器作用:
可以滤掉信号抖动的干扰,在一个固定的时钟频率f下进行采样,如果连续n个采样点都为相同的电平,那就代表输入信号稳定了,就把该采样值输出出去;如果连续n个采样点不完全相同,那么就说明信号有抖动,这时就保持上一次的输出,或者直接输出低电平。此时采样频率f和采样点数n 都是滤波器的参数。采样频率可以直接有内部时钟接入,也可以内部时钟加一个时钟分频而来。分频多少由clock division决定。TIM_TimeBaseInitStructure.TIM_ClockDivisio
#include "stm32f10x.h" // Device header
extern 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;//配置采样频率(滤波器),消除抖动;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;//计数器模式——向上计数
TIM_TimeBaseInitStructure.TIM_Period=10000-1;//ARR自动重装器的值
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;//预分频器的值 72MHz/7200/10000=1
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//重复计数器的值(高级计数器才需要,目前不需要用给0即可)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//时基单元配置完毕 更新事件和更新中断是同时发生的,
//第三步配置输出中断控制,允许更新中断输出到NVIC。
TIM_ClearFlag(TIM2,TIM_FLAG_Update);//清除更新事件带来的更新中断标志位的变化,否则会导致上电立刻进入中断
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能中断;开通更新中断到NVIC的通路
//第四步配置NVIC,在NVIC中打开定时器中断通道,并分配一个优先级。
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;//定时器2在NVIC里的通道
NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStruct);
//第五步使能计数器
TIM_Cmd(TIM2,ENABLE);//开启定时器;
}
void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2,TIM_IT_Update)==SET)
{
Num++;
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}