相关理论部分TIM简介
(Timer) 定时器
定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。
16位计数器、预分频器、自动重装寄存器的时基单元,在72MHZ计数时钟下可以实现最大59.65s的定时。
不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。
根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型
定时器类型
STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4。
基本定时器
PSC预分频器(16bit)、CNT计数器(16bit)、自动重装载寄存器(16bit)由它们三个所构成的基本计数计时电路叫做时基单元。由于基本计时器只能选择内部时钟,则可直接理解为跳过了控制器直接与内部时钟(CK_INT)相连接,内部时钟的来源RCC的TIMxCLK一般为系统主频72MHz。而预分频器可以对72MHz的计数时钟进行预分频,如果此寄存器写0,则不进行分频,输出频率依旧为72HMz;写0则二分频,输出频率为36MHz,写2为三分频,输出频率为24MHz。
CNT计数器:计数时钟每来一个上升沿计数器的值就加1。
自动重装载寄存器:写入一个自动重装值,当自增运行到自动重装值时,产生中断,并将计数器清零。
代表这里会产生中断信号,像计数值等于自动重装值产生的中断,叫做更新中断,此信号这时会通往NVIC。
代表的是会产生一个事件,叫做更新事件,它不会触发中断但可以触发内部其他电路的工作。
通用计时器
通用定时器和高级定时器的计数器支持向上计数,向下计数和中央对齐计数三种模式。
时钟源
1)内部时钟(CK_INT)
2)外部时钟模式 1:外部输入引脚(TIx),x=1,2(即只能来自于通道 1 或者通道 2)
3)外部时钟模式 2:外部触发输入(ETR)
4)内部触发输入(ITRx):使用一个定时器作为另一定时器的预分频器
外部时钟源模式1
1.外部时钟源信号→IO→TIMx_CH1(或者 TIMx_CH2),其中,外部时钟模式 1 下,时钟源信号只能从 CH1 或者 CH2 输入到定时器,CH3 和 CH4 都是不可以的。
2.TI2 首先经过一个滤波器,由 ICF[3:0]位来设置滤波方式,也可以设置不使用滤波器。
3.接着经过边沿检测器,由 CC2P 位来设置检测的边沿,可以上升沿或者下降沿检测。
4.然后经过触发输入选择器,由 TS[4:0]位来选择 TRGI(触发输入信号)的来源。 TI1F_ED、TI1FP1 和 TI2FP2 三个触发输入信号(TRGI)。
5.最后经过模式选择器,由 ECE 位和 SMS[2:0]位来选择定时器的时钟源。外部时钟模式 1,ECE 位置 0,SMS[2:0] = 111。
6.CK_PSC 需要经过定时器的预分频器分频后,最终就能到达计数器进行计数了。
外部时钟源模式2
1.外部时钟源信号→IO→TIMx_ETR,需配置 IO 的复用功能,才能使IO 和定时器相连通。
2.经过外部触发极性选择器,由 ETP 位来设置上升沿有效还是下降沿有效,选择下降沿有效的话,信号会经过反相器。
3.然后经过外部触发预分频器,由 ETPS[1:0]位来设置预分频系数,系数范围:1、2、4、8。
4.紧接着经过滤波器器,由 ETF[3:0]位来设置滤波方式,也可以设置不使用滤波器。fDTS 由TIMx_CR1 寄存器的 CKD 位设置。
5.从模式选择器,由 ECE 位置 0和 SMS[2:0]位来选择定时器的时钟源。
6.CK_PSC 需要经过定时器的预分频器分频后,最终就能到达计数器进行计数了。
定时中断基本结构图
RCC时钟树
程序源码功能实现
让定时器工作的基本步骤,可以参考定时器中断基本结构图。
1.RCC开启时钟。(打开此时钟后定时器的基准时钟和外设的工作时钟就都会同时打开了)
2.选择时基单元的时钟源(这里选择内部时钟源)
3.配置时基单元
4.配置输出中断控制,允许更新中断输出到NVIC。
5.配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。
6.运行控制。
时钟源选择的函数
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捕获通道的时钟
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引脚的预分频器、极性、滤波器参数。
Timer.c
#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 ;
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 ;
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);
}
}
*/