stm32(十一)基本定时器

一、简介

STM32f40x 芯片一共有 14 个定时器,分为 3 类

  •  基本定时器

ST32F40x 基本定时器包括 TIM6 和 TIM7。基本定时器只提供基本的定时功能以及 DAC 触发功能。

  • 通用定时器

ST32F40x 通用定时器包括 TIM2、 TIM3、 TIM4、 TIM5 和 TIM9、 TIM10、 TIM11、 TIM12、 TIM13 以及 TIM14。
通用定时包含基本定时器的功能,同时还具有输入捕获、输出比较, PWM 输入以及 PWM 输出。

  • 高级定时器

ST32F40x 高级定时器包括 TIM1 和 TIM8。高级定时器包含通用定时器的功能,同时还具有 PW 互补输出、
死区功能以及刹车功能。

 在【STM32F4资料\1.手册\STM32F407ZGT6.pdf】的P17时钟树中可知:

2、STM32F407ZGT6的基本定时器概述

STM32F407ZGT6基本定时器有两个,分别是TIM6和TIM7。基本定时器的特性:①16 位自动重载递增计数器;②16 位可编程预分频器,用于对计数器时钟频率进行分频(即运行时修改),分频系数介于 1 和 65536 之间;③发生计数器上溢时会生成中断(前提是使能更新中断)。

3、STM32F407ZGT6的基本定时器框图讲解

  • 定时器的最大计数频率(时钟频率)是84MHZ,即图中的CK_INT。
  • 基本定时器有一个预分频器,分频值1 和 65536,作用是:降低计数频率(时钟频率),分频后的计数频率(时钟频率)是上图中的CK_CNT
  • 基本定时器的工作原理:编程时,先确定计数频率CK_CNT,然后给“自动重装载寄存器 ”赋值,然后“定时器计数器寄存器”在CK_CNT的频率下进行自增,如果增加到与“自动重装载寄存器 ”中的值相等时,则定时时间到达,同时会产生更新事件(如果使能中断,则会产生更新中断),简答得说:定时的过程就是“定时器计数器寄存器”的值和自动重装载寄存器 ”实时比较的一个过程。
  • 时基单元:①计数器寄存器 (TIMx_CNT);②预分频器寄存器 (TIMx_PSC);③自动重载寄存器 (TIMx_ARR)
  • 时基单元的每个寄存器都是16位。

自动重装载寄存器的“影子寄存器”:是否使用“影子寄存器”取决于TIMx_CR1 (x:6~7)寄存器中的自动重载预装载使能位 (ARPE)。如果使能自动重载预装载使能位,则影子寄存器有效;否则无效。①如果使能自动重载预装载使能位,则影子寄存器有效,计时的过程是“计数器寄存器 (TIMx_CNT)”和“自动重载寄存器 (TIMx_ARR)的影子寄存器”的一个比较过程。如果定时器时间没有到达,即还在计时中,此时修改了“自动重载寄存器 (TIMx_ARR)”,要在上一次定时时间到达后才会更新“影子寄存器”。(因此可对自动重载寄存器 (TIMx_ARR)进行任意更改。而新的自动重装载值将在下一更新事件发生时被采用)。举例:假如第一次定时时间为1000ms,定时时间还没到,当前已经计数计时到了350ms,此时,修改定时时间为500ms,定时时长设置不会马上生效,而是要等到定时1000ms并产生更新事件后才会有效。

②如果不使能自动重载预装载使能位,则影子寄存器无效,计时的过程是“计数器寄存器 (TIMx_CNT)”和“自动重载寄存器 (TIMx_ARR)”的一个比较过程。随时更新“自动重载寄存器 (TIMx_ARR)”的值,都可以马上改变定时时长。举例:假如第一次定时时间为1000ms,定时时间还没到,当前已经计数计时到了350ms,此时,修改定时时间为500ms,定时时长设置会马上生效,则在定时到500ms时就会产生更新事件。

  • 预分频器寄存器 (TIMx_PSC)也有“缓冲”,“缓冲”是永远有效的,由于 TIMx_PSC 预分频寄存器有缓冲,因此可对预分频器进行任意更改。而新的预分频比将在下一更新事件发生时被采用。
  • 计数器从 0 计数到自动重载值( TIMx_ARR 寄存器的值)并生成计数器上溢事件,如果TIMx_CR1寄存器的OPM位置1,则定时器重新又从 0 开始计数。每次发生计数器上溢时会生成更新事件。

4、相关寄存器

4.1、TIM6 TIM7 控制寄存器 1 (TIMx_CR1)

位 0 CEN  计数器使能 (Counter enable)

0:禁止计数器
1:使能计数器

位 1 UDIS  更新禁止 (Update disable)

0:使能更新 (UEV),更新事件可通过以下事件之一生成:①计数器上溢②将 UG 位置 1

1:禁止 更新UEV。定时到达后不会生成更新事件。

位 2 URS  选择更新请求源 (Update request source)

0:所有以下事件都会生成更新中断。此类事件包括:①计数器上溢;②将 UG 位置 1
1:只有计数器上溢才会生成更新中断。

位 3 OPM  单脉冲模式 (One-pulse mode)

0:计数器在发生更新事件时不会停止计数
1:计数器在发生下一更新事件时停止计数(将 CEN 位清零)。

位 7 ARPE  自动重载预装载使能 (Auto-reload preload enable)

0: TIMx_ARR 寄存器不进行缓冲(影子寄存器无效)。
1: TIMx_ARR 寄存器进行缓冲(影子寄存器有效)。

举例:定时器6使能ARR自动重装载寄存器的影子寄存器,重复定时,允许计数器上溢产生更新请求且允许UG位置1产生更新请求,使能定时器6:

TIM6->CR1 |= 1<<7;    

TIM6->CR1&=~(1<<3);

TIM6->CR1&=~(1<<1);

TIM6->CR1&=~(1<<2);

TIM6->CR1|=1<<0;

4.2、​​​​​​TIM6 TIM7 DMA/中断使能寄存器 (TIMx_DIER)

位 0 UIE  更新中断使能 (Update interrupt enable)

0:禁止更新中断。
1:使能更新中断。所谓的“更新中断”可以理解为“定时器中断”。

举例:定时器6使能更新中断 TIM6->DIER |= 1<<0;

4.3、TIM6 TIM7 状态寄存器 (TIMx_SR)

位 0 UIF  更新中断标志 (Update interrupt flag)

该位有硬件置1,软件清零。

0:未发生更新(即:定时时间还没到)。
1:更新中断挂起,由以下两种因素导致该位硬件置1:
①定时器计数器上溢会导致该位置1(即该位置1表示定时时间到达)

②UG位置1也会导致该位置1(前提:TIMx_CR1 寄存器中 URS = 0 且 UDIS = 0)

总结:导致产生更新中断标志位置1并且产生更新中断的因素有两个

举例:定时器7的中断函数

void  TIM7_IRQHandler(void)
{
   if(TIM7->SR&(1<<0))  //判断中断标志是否置1
   {
      TIM7->SR &=~(1<<0);//中断标志清零
      //中断代码
   }
}

4.4、TIM6 TIM7 事件生成寄存器 (TIMx_EGR)

位 0 UG  更新生成 (Update generation)

该位可通过软件置 1,并由硬件自动清零。

0:不执行任何操作。

1:重新初始化定时器计数器(TIMx_CNT)并生成寄存器更新事件。

举例:使用UG位置1来初始化TIM6_CNT寄存器 TIM6->EGR |= 1<<0;

4.5、​​​​​​​TIM6 TIM7 预分频器 (TIMx_PSC)

15:0 PSC[15:0]  预分频器值 (Prescaler value)

计数器时钟频率 CK_CNT 等于 fCK_PSC / (PSC[15:0] + 1)
PSC 包含在每次发生更新事件时要装载到实际预分频器寄存器的值。

举例:已知TIM6的时钟频率 fCK_PSC是84MHZ,如何分频可以让CK_CNT的频率为10KHZ?即IM6->PSC = 8400 -1;

4.6、​​​​​​​TIM6 TIM7 自动重载寄存器 (TIMx_ARR)

该寄存器16位有效,主要用于和“计数器寄存器”进行比较,如果“计数器寄存器”的值自增到与“自动重装载寄存器”的值相等,则溢出,即定时时间到达。

举例:已知TIM6的时钟频率 fCK_PSC是84MHZ,如何分频可以让CK_CNT的频率为10KHZ?如果CK_CNT为10KHZ,则自动重装载寄存器赋值多少可以实现1s的定时?

TIM6->PSC = 8400 -1;

计算公司Tout= ((arr+1)*(psc+1))/Tclk;故

((1+TIM_Prescaler )/84M)*(1+TIM_Period )=((8400)/84M)*(1+TIM_Period )=1秒*/

TIM_Period  = 10000;

TIM6->ARR=10000;

4.7、​​​​​​​APB1 外设时钟使能寄存器(RCC_APB1ENR)

该寄存器主要关注位8~位0,相应位置1则使能相应外设的时钟

举例:使能定时器6的时钟,RCC->APB1ENR |= 1<<4;

​​​​​​​4.8、TIM6&TIM7的中断函数与中断端通道编号

该表格主要查阅startup_stm32f40_41xxx.s 和 stm32f4xx.h

5、编程思路

  1. 使能定时器的相应时钟,即RCC->APB1ENR的相应位置1
  2. TIMx_ARR 寄存器进行缓冲
  3. 计数器在发生更新事件时不会停止计数(循环计数,循环定时)
  4. 使能更新 (UEV)
  5. 选择更新请求源
  6. 使能更新中断
  7. UG位置1重新初始化定时器计数器(TIMx_CNT)
  8. 状态寄存器清零
  9. 配置预分频值
  10. 配置自动重装载值
  11. 使能定时器中断中断通道,调用NVIC_EnableIRQ函数,如果要调整抢占和响应的优先级,请参考第五章的内容。
  12. 使能定时器

6、软件设计

实现定时器7控制LED灯亮灭。每秒钟取反一次LED灯的状态。

寄存器版

void TIM7_Init(u16 psc, u16 arr)
{
	RCC->APB1ENR |= 1<<5;//使能定时器7的时钟
	TIM7->CR1 |= 1<<7;  //TIM7_ARR 寄存器进行缓冲
	TIM7->CR1&=~(1<<3);//计数器在发生更新事件时不会停止计数(循环计数,循环定时)
	TIM7->CR1&=~(1<<1);//使能更新 (UEV)
	TIM7->CR1&=~(1<<2);//选择更新请求源,允许①计数器上溢;②将 UG 位置 1 ,这两种情况产生更新事件
	TIM7->DIER |= 1<<0;//使能更新中断
	TIM7->EGR |= 1<<0;//UG位置1重新初始化定时器计数器(TIMx_CNT)
	TIM7->SR = 0;//状态寄存器清零
	TIM7->PSC = psc;//配置预分频值
	TIM7->ARR = arr;//配置自动重装载值
	NVIC_EnableIRQ(TIM7_IRQn);//使能定时器中断中断通道
	TIM7->CR1|=1<<0;//使能定时器
}
void  TIM7_IRQHandler(void)
{
   if(TIM7->SR&(1<<0))  //判断中断标志是否置1
   {
      TIM7->SR &=~(1<<0);//中断标志清零
      GPIOF->ODR ^= (1<<6);//使用异或操作,取反GPIOF->ODR的位6的值
   }
}
int main(void)
{
	LED_Init();
	TIM7_Init(8400 -1,10000);
	while(1)
	{
	}
}

库函数版

void TIM7_Init(u16 psc, u16 arr)
{
	NVIC_InitTypeDef NVIC_InitStructure;
	TIM_TimeBaseInitTypeDef TIM7_TimeBaseInitTypeDef;
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7,ENABLE); //①使能 TIM7 时钟
	TIM7_TimeBaseInitTypeDef.TIM_Period = arr; //自动重装载值
	TIM7_TimeBaseInitTypeDef.TIM_Prescaler=psc; //定时器分频
	TIM7_TimeBaseInitTypeDef.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
	TIM7_TimeBaseInitTypeDef.TIM_ClockDivision=TIM_CKD_DIV1;
	TIM_TimeBaseInit(TIM7,&TIM7_TimeBaseInitTypeDef);// ②初始化定时器 TIM7
	TIM_ITConfig(TIM7,TIM_IT_Update,ENABLE); //③允许定时器 7 更新中断
	NVIC_InitStructure.NVIC_IRQChannel=TIM7_IRQn; //定时器 7 中断
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);// ④初始化 NVIC
	TIM_Cmd(TIM7,ENABLE); //⑤使能定时器 7
	
}
void  TIM7_IRQHandler(void)
{
   if(TIM_GetITStatus(TIM7,TIM_IT_Update)==SET) //溢出中断
		{
		  GPIO_ToggleBits(GPIOF,GPIO_Pin_6);
		}
		TIM_ClearITPendingBit(TIM7,TIM_IT_Update); //清除中断标志位
}
int main(void)
{
	LED_Init();
	TIM7_Init(8400 -1,10000);
	while(1)
	{
	}
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值