嵌入式学习---定时器定时篇

目录

1. 定时器的分类

2. 定时器特性及功能

3. 定时器和计数器的区别

4.代码实现及分析                                           

    4.1配置代码 

    4.2配置思路讲解

     4.3时间计算及注意点


(定时器内容较多,本文主要讲解其定时功能及实现)

1. 定时器的分类

在STM32F1系列单片机中,定时器分为以下几种类型:

(1)高级定时器 :

  • 通常包括TIM1和TIM8。
  • 支持多种操作模式,如正交编码器接口(QEI)。
  • 提供多达4个捕获/比较通道,可用于产生复杂的PWM波形。

(2)通用定时器 :

  • 通常包括TIM2、TIM3、TIM4和TIM5。
  • 通常拥有4个独立的捕获/比较通道,可以配置为输入捕获或输出比较/PWM。
  • 支持向上计数、向下计数或中心对齐模式。

(3)基本定时器 :

  • 通常包括TIM6和TIM7。
  • 只有定时和中断功能,只能向上计数,不具备输入输出通道。


2. 定时器特性及功能

在STM32F1系列单片机中,定时器主要有以下特性:

  • 16位自动装载计数器: 计数器可以在向上计数到最大值后自动重置为零,或者在向下计数到零后自动重置为最大值。
  • 16位可编程预分频器: 允许用户根据需要调整计数器时钟频率
  • 捕获/比较通道: 用于输入捕获或输出比较,可以生成PWM信号
  • 中断和DMA支持: 提供中断请求和DMA传输触发,便于数据处理。
  • 多种工作模式: 包括向上计数、向下计数、中心对齐模式等。

主要有以下功能 :

基本功能:

(1)计数功能:

  • 向上计数: 从0开始递增计数直到最大值。
  • 向下计数: 从最大值开始递减计数直到0。
  • 中心对齐计数: 结合了向上和向下计数的特点,可以实现更复杂的计数模式。

(2)预分频功能:

  • 可以通过预分频器来调整计数器的时钟频率,从而改变计数速度。

(3)自动装载功能:

  • 当计数器达到最大值或最小值时,自动装载寄存器中的值会被加载到计数器中,使得计数器能够循环计数。

高级功能:

(1)捕获/比较功能:

  • 输入捕获: 通过外部信号触发捕获事件,记录捕获时刻的计数值。
  • 输出比较: 将计数器值与预设值进行比较,当两者相等时触发输出事件。

(2)PWM输出:

  • 通过输出比较功能可以生成PWM信号,用于电机控制、LED亮度调节等。

(3)死区插入:

  • 在某些定时器中,可以配置死区插入功能来避免高边和低边开关同时导通的情况。

(4)同步功能:

  • 定时器之间可以同步操作,比如一个定时器可以作为另一个定时器的时钟源。

(5)中断和DMA支持:

  • 支持中断请求,以便在特定事件发生时执行中断服务程序。
  • 支持DMA传输,可以在定时器事件发生时自动传输数据。

特殊功能:

  • 正交编码器接口 (QEI): 高级定时器支持正交编码器接口,用于测量旋转编码器的速度和位置。
  • 刹车功能: 在某些应用中,可以配置定时器的刹车功能来快速停止计数器。

应用场景:

  • 定时任务: 用于周期性地执行任务,如定时更新传感器读数。
  • PWM输出: 用于控制电机速度及方向、驱动无源蜂鸣器、调节LED亮度等。
  • 脉冲测量: 通过输入捕获功能测量外部脉冲的宽度或频率。
  • 通信协议: 用于实现SPI、I²C等通信协议中的定时要求。

这些功能使得STM32定时器成为一种非常灵活且强大的外设,可以广泛应用于各种嵌入式系统的设计中。



3. 定时器和计数器的区别

刚接触定时器外设的时候,总觉得定时器就是计数器,以为是同一个东西的不同叫法,实际上并非如此,它们虽然相似,但是却并不是同一个东西。以下是它们的区别:

定时器:

(1)计数对象:

  • 定时器通常计数的是内部时钟信号,这种信号具有固定的周期。

(2)计数目的:

  • 定时器主要用于产生预定的时间间隔或周期,通过计数内部时钟信号的周期数来实现。

(3)应用场景:

  • 定时器常用于实现定时任务、PWM信号生成、周期性中断等。

计数器:

(1)计数对象:

  • 计数器可以计数外部事件或信号,这些信号的周期和频率可以变化。

(2)计数目的:

  • 计数器主要用于统计外部事件的发生次数,也可以用来测量脉冲的宽度或频率。

(3)应用场景:

  • 计数器常用于脉冲宽度测量、频率测量、外部事件计数等。

主要区别总结:

(1)计数信号来源:

  • 定时器使用内部时钟信号,其频率通常是固定的。
  • 计数器可以使用外部信号,其频率可以是变化的。

(2)用途:

  • 定时器主要用于实现定时功能,如定时中断、PWM信号生成等。
  • 计数器主要用于计数外部事件,如脉冲计数、频率测量等。

(3)计数方式:

  • 定时器通常使用固定的时钟频率进行计数,因此可以计算出时间间隔。
  • 计数器则根据外部事件触发计数,用于统计事件发生的次数或测量事件的时间间隔。

(4)输出功能:

  • 定时器通常可以配置为输出比较功能,生成PWM信号。
  • 计数器主要关注输入捕获功能,用于捕捉外部事件。


4.代码实现及分析                                           

    4.1配置代码 
/*********************************************************************
 @Function   : 定时器初始化
 @Parameter  : arr:自动重装值
			   psc:时钟预分频数
 @Return     : N/A
 @Read 		 :Tout=((arr+1)*(psc+1))/Ft us,Ft=定时器工作频率,单位:Mhz
**********************************************************************/
void Timer_Init(uint16_t psc, uint16_t arr)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
    /*时钟使能*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); 
    /*TIM配置*/
	TIM_TimeBaseStructure.TIM_Prescaler = psc;   //预分频值
	TIM_TimeBaseStructure.TIM_Period = arr;     //周期值	
	TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //时钟分频系数1 即不分频 
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //向上计数
	TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); 
    /*使能中断*/
	TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE ); 
	/*NVIC 配置*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;  
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  //抢占优先级0
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;         //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 
	NVIC_Init(&NVIC_InitStructure);  
    /*使能TIM4*/
	TIM_Cmd(TIM4, ENABLE);  
}

/*********************************************************************
 @Function  : 定时器中断服务函数
 @Parameter : N/A
 @Return    : N/A
**********************************************************************/
void TIM4_IRQHandler(void)   
{	
    uint8_t count = 0;
	if(TIM_GetITStatus(TIM4, TIM_IT_Update) == SET)  //溢出中断
	{
        count++;
		if(count == 10)	 //定义中断周期
		{	
		   count= 0;
		   //你要在中断做的事情
		}
	}
	TIM_ClearITPendingBit(TIM4,TIM_IT_Update);     //清除中断标志位
}


    4.2配置思路讲解
  • 首先是定义对应的结构体,使能对应的时钟。我这里需要中断功能,因此加了NVIC的。

想一想:为什么NVIC没有开时钟呢?没开时钟这NVIC功能能用吗?答案是可以。因为中断功能属于片内核心功能,NVIC是ARM Cortex-M架构的一部分,它和CPU核心共享相同的电源域与时钟源,无需单独再为NVIC配置时钟

  • 其次是给两个结构体配置参数。需要中断,所以使能定时器中断,再为这个中断分配个优先级就OK啦。
  • 定时器使能。
  • 定时器中断服务函数

TIM_GetITStatus(TIM4, TIM_IT_Update)获取中断状态,因为配置的是向上计数模式,所以相应的中断就是TIM_IT_Update向上计数中断。     定义count,这个是大周期的执行次数,之前已经定义大周期为1ms,当中断发生一次,就说明大周期执行一次,即1ms过去了。那么我就count++,记下大周期的执行次数。如果我想要我的某些功能10ms运行一次,只需要判断count是否等于10,如果等于就进入,不等于继续count++。     把count清零,让程序一直以10ms周期执行下去。    每次进入中断都要把中断标志位清除,为检测定时器下次中断做准备。



     4.3时间计算及注意点

这里着重讲下定时时间如何计算:

所谓定时时间,其实就是定时器的周期值。首先要知道你的芯片频率,假如是72MHz。

  • TIM_CKD_DIV1  时钟1分频,即72MHz/1=72MHz。如果是TIM_CKD_DIV2 ,那就是72MHz/2=36MHz,其他参数同理。一般这个设置为1分频就行。
  • TIM_Prescaler 就是预分频值,因为这个72MHz太快了,它的周期是1/72M秒(s),要把它变慢点,所以就分频,假如我分频值为7200,那么这个频率就会变成72M/7200=10000Hz它的周期是1/10000秒=10微秒(us)
  • 现在我需要周期1毫秒(ms)的定时,就是在小周期10us的情况下,要达到1ms的大周期 。那么就需要计算多少个10us等于一个1ms,TIM_Period = 1ms/10us = 1000us/10us = 100次,即小周期要运行100次才达到1ms这个大周期。

总结:TIM_Prescaler 预分频值,把时钟变慢,周期变长,称之为小周期TIM_Period自动重装载值,是一个小周期循环次数,通过循环得到自己想要的周期,称之为大周期

注意一下TIM_Prescaler和TIM_Period的值都需要减1,比如7200和100,就要写成7199和99,也可写成(7200-1)和(100-1),这样能更方便看出想要定义的值是7200和100。

具体原因是预分频值的寄存器会自动把寄存器的值加1,这种设计使得你可以实现从1到65536的分频比。如果预分频值直接使用而不加1,则无法实现分频比为1的情况(即不分频),因为最小值0会导致分频比为0,这是无效的。自动重装载值的寄存器是从0开始计数的,0到99正好是100。

定时器的定时功能部分到这里就结束了,觉得有用可以点个赞再走~。后面会继续更新定时器的其他功能。如果有不对的地方欢迎指出,一定虚心改正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值