通用定时器工作过程:
在这里插入图片描述
时钟选择:

计数器时钟可以由下列时钟源提供:

  • 内部时钟(CK_INT)
  • 外部时钟模式1:外部输入脚(TIx)
  • 外部时钟模式2:外部触发输入(ETR)
  • 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。

内部时钟选择
在这里插入图片描述
在这里插入图片描述
时钟计算方法:
在这里插入图片描述默认调用SystemInit函数情况下:
SYSCLK=72M
AHB时钟=72M
APB1时钟=36M
所以APB1的分频系数=AHB/APB1时钟=2
所以,通用定时器时钟CK_INT=2*36M=72M

计数器模式: 通用定时器可以向上计数、向下计数、向上向下双向计数模式。

  • 向下计数模式(时钟分频因子=1(意思就是:CK_PSC=CK_CNT))

在这里插入图片描述在这里插入图片描述

  • 向上计数模式(时钟分频因子=1)
    在这里插入图片描述
    在这里插入图片描述

  • 中央对齐计数模式(时钟分频因子=1 ARR=6)
    在这里插入图片描述
    在这里插入图片描述
    定时器中断实验相关寄存器:

  • 计数器当前值寄存器CNT
    在这里插入图片描述

  • 预分频寄存器TIMx_PSC

在这里插入图片描述

  • 自动重装载寄存器(TIMx_ARR)
    在这里插入图片描述
  • 控制寄存器1(TIMx_CR1)
    在这里插入图片描述
  • DMA中断使能寄存器(TIMx_DIER)
    在这里插入图片描述

常用库函数

定时器参数初始化:

 void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
ypedef struct
{
  uint16_t TIM_Prescaler;//预分频系数的设置      
  uint16_t TIM_CounterMode;//计数模式   
  uint16_t TIM_Period;//自动装载值
  uint16_t TIM_ClockDivision;//输入捕获会用到 
  uint8_t TIM_RepetitionCounter;//高级定时器会用到
} TIM_TimeBaseInitTypeDef; 
TIM_TimeBaseStructure.TIM_Period = 4999;
TIM_TimeBaseStructure.TIM_Prescaler =7199; 
TIM_TimeBaseStructure.TIM_ClockDivision =TIM_CKD_DIV1; 
TIM_TimeBaseStructure.TIM_CounterMode =TIM_CounterMode_Up; 
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); 

定时器使能函数:

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)

定时器中断使能函数:

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

状态标志位获取和清除:

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);

定时器中断实现步骤:

  • 能定时器时钟。
 RCC_APB1PeriphClockCmd();
  • 初始化定时器,配置ARR,PSC。
 TIM_TimeBaseInit();
  • 开启定时器中断,配置NVIC。
void TIM_ITConfig();
      NVIC_Init();
  • 使能定时器。
TIM_Cmd();
  • 编写中断服务函数。
TIMx_IRQHandler();//中断函数要判断中断标志位,和手动清除中断标志位
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

Tout(溢出时间)=(ARR+1)(PSC+1)/Tclk

其中arr为你重装的值,

psc是预分频计时器的值(预分频系数),

Tclk是时钟频率

Tclk/(psc+1)是定时器的时钟

(psc+1))/Tclk*1是计算的计数器 减少/增加 一个数所用的时间;

那么(psc+1))/Tclk*(arr+1)就是一次定时器的时间:

然后继续重装arr再次计数,计时:

就构成一个循环;

  • TIM2-TIM5的时钟不是直接来自于APB1,而是来自于输入为APB1的一个倍频器。这个倍频器的作用是:当APB1的预分频系数为1时,这个倍频器不起作用,当APB1的预分频系数为其他数值时(即预分频系数为2、4、8或16),这个倍频器起作用,定时器的时钟频率等于APB1的频率的2倍。
  • 分频系数就是对定时器时钟进行多少分频之后在使用,最好设置为定时器时钟的倍数,方便运算;重新装载值是计算这么多值,时间到了之后重新开始计算的值,每一次计数的时间为分频之后时钟的到时;

假设定时器时钟为72M,分频系数设置为7200-1,那现在定时器的时钟为10kHz,每计一个数花费1/(10000)秒,重装值设置为5000-1,那一次溢出的时间为500ms。
分频值是是指你将系统时钟的频率减小,假设时钟频率是 72Mhz,然后分频值是 7199,现在你的定时器值就是 10kHz,表示每计一个数,然后过了 1/(10^4)秒,然后你的重装值就是你的时间了,如果值是 9999,就表示定时时间为 1s。

定时器配置代码:

void TIM4_Init(u16 ar,u16 rs)
{
	TIM_TimeBaseInitTypeDef TIM_InitStrue;
	NVIC_InitTypeDef NVIC_InitStrue;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能定时器时钟
	
	TIM_InitStrue.TIM_Period=ar;//自动装载值
	TIM_InitStrue.TIM_Prescaler=rs;//预分频系数的设置
	TIM_InitStrue.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_InitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseInit(TIM4,&TIM_InitStrue);//初始化定时器,对定时器进行配置
	
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE);//开启定时器中断
	
	NVIC_InitStrue.NVIC_IRQChannel=TIM4_IRQn;
	NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStrue.NVIC_IRQChannelSubPriority=2;
	NVIC_Init(&NVIC_InitStrue);//初始化中断,设置中断的优先级

	TIM_Cmd(TIM4,ENABLE);//使能定时器
}

void TIM4_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM4,TIM_IT_Update)!=RESET)
	{
		LED1=!LED1;
		TIM_ClearITPendingBit(TIM4,TIM_IT_Update);//清除中断标志位
	}
}	

实验现象:LED0闪烁,时间间隔就是定时器的溢出时间

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐