首页 > 其他分享 >TIM定时器(标准库)

TIM定时器(标准库)

时间:2024-10-13 23:19:34浏览次数:7  
标签:TIM2 定时器 标准 中断 NVIC TIM 时钟

目录

一. 前言

二. 定时器的框图

三. 定时中断的基本结构

 四. TIM定时器相关代码

五. 最终现象展示


一. 前言

        什么是定时器? 定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。

TIM定时器不仅具备基本的定时中断功能,而且还包含内外时钟源选择,输入捕获,输出比较,编码器接口,主从触发模式等多种功能。

根据复杂度和应用场景分为了高级定时器,通用定时器,基本定时器。它们包含的编号以及分布总线和功能如下所示:

 其中,我们可以看到高级定时器是连接在APB2总线上的,所以前面介绍的APB2性能更高是没有问题的。

值得注意的是:不是所有的单片机芯片都拥有所有的定时器。例如我们的STM32F103C8T6就只拥有四个定时器资源:TIM1,TIM2,TIM3,TIM4。

二. 定时器的框图

        基本定时器的基本框图如下所示:

如上所示,我们基本定时器主要就是通过预分频器对时钟进行预分频,然后计数器就自增计数。当计数值达到自动重装值时,计数值清零同时产生更新中断和更新事件。

       通用定时器的基本框图如下所示:

我们可以看出,通用定时器比基本定时器的框图复杂了很多,主要是因为我们上面所介绍的它们的功能。 基本定时器只拥有定时中断,主模式触发DAC的功能。而我们的通用定时器不仅具备基本定时器的全部功能,并且还额外拥有内外时钟源选择,输入捕获,输出比较,编码器接口,主从触发模式等功能。例如上面框图中左下角的部分---输入滤波器和边沿检测器就是为我们通用定时器的输入捕获而设计的。

        高级定时器的框图如下所示:

高级定时器主要就是在通用定时器的基础上新增了重复计数器(这里后面会涉及的,只有高级定时器才具备),死区生成,互补输出,刹车输入等功能。

三. 定时中断的基本结构

        我们想要配置好定时器,并使用它,只需要根据它的基本结构来一个一个进行相关配置即可。定时中断的基本结构如下所示:

总结一下,就是:

1) 首先配置好时钟,选择内部时钟RCC还是外部时钟ETR等等。这里需要的库函数在tim.h当中寻找。如果选择内部时钟,那么就需要使用TIM_InternalClockConfig()这个库函数。

2) 然后进行时基单元的配置。选择TIM_TimeBaseInit()函数。

对于其中的Period(重装载值ARR)和Prescaler(分频系数PSC)的取值都要在0~65536之间,因为它们都是16位的。这两个的取值不是唯一的,可以分频系数PSC给少点,自动重装给多点,这样就是以一个比较高的频率计比较多的数。

值得注意的是,为了方便更改其中一些具体的参数,如分频值等。ST公司提供了一些库函数,专门单独更改。例如TIM_PrescalerConfig()函数,就是用来单独写预分频值的。还有很多小的函数,这些大家看到都可以查询一下,很容易就能查到。这里我就不过多一一介绍了。

另外,在时基单元中的预分频器中,最重要的其实是预分频缓冲器。它可以防止计数中途更改数值造成错误。

3)配置输出中断控制,允许更新中断输出到NVIC。这里使用库函数TIM_ITConfig()。

4)配置NVIC。这个之前讲过,根据之前的进行相关配置即可。

值得注意的是,定时器相关的GPIO配置,需要根据产品手册来查看,例如定时器2的GPIO配置就为浮空输入,这个地方在产品手册中的通用I/O(GPIO)位置查看,如下所示:

 四. TIM定时器相关代码

        上面已经讲过了TIM配置的流程,所以我们根据它来即可。我们只需要明确一点,那就是使用定时器根据它的基本结构来配置就行了。将它的结构都打通,不就可以运行定时器了吗。

首先就是开启对应的时钟,这里我们选择使用TIM2。如下所示:

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

然后选择时钟源,这里选择内部时钟源。如下所示:

TIM_InternalClockConfig(TIM2);

值得注意的是,如果有小伙伴对库函数参数配置不理解。可以在自己工程中找到该库函数,然后鼠标右键点击跳转到定义处,就可以查看库函数各个参数的作用了。

然后对时基单元进行初始化:

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    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; //这里是高级定时器才具备的重复计数功能,所以我们置为0即可		
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);		

对于其中的Period和Prescaler值,我觉得还有必要讲下。这两个值就是ARR和PSC的值。由于我们单片机的主频率也就是72MHz。所以定时器的频率CK_CNT=72000000/(PSC+1)/(ARR+1)。

当我们的PSC为7200-1,ARR为10000-1时,那么最后CK_CNT的结果就为1Hz,也就是1s。

接着我们可以清除下定时器更新标志:

TIM_ClearFlag(TIM2, TIM_FLAG_Update);	

若是不清除这个标志位,那么开启中断后,会立刻进入一次中断。例如我们点击复位按钮,理论上是从0开始计数的,但是如果不清楚这个标志位,那么它就会从1开始计数。这是不符合常理的。

开启更新中断输出使能中断:

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

 进行NVIC的相关配置:

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);				
	
	/*NVIC配置*/
	NVIC_InitTypeDef NVIC_InitStructure;						
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;				
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;		
    NVIC_InitStructure.NVIC_IRQChannerPreemptionPriority=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)
	{
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
}

例如因为我们上面已经配置好了定时器为1s的计时。我们可以让它每次达到计数值的时候,进行数字的加1,最后显示在OLED上。如下所示,只需要加一行代码即可。至于显示到OLED上或者其他操作,大家可以自由发挥尝试。

void TIM2_IRQHandler(void)
{
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)		//判断是否是TIM2的更新事件触发的中断
	{
		Num ++;												//Num变量自增,用于测试定时中断
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);			//清除TIM2更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

五. 最终现象展示

 

 

        

        

 

标签:TIM2,定时器,标准,中断,NVIC,TIM,时钟
From: https://blog.csdn.net/2303_78660417/article/details/142894033

相关文章

  • C++之multimap:关键字分类的利器
    目录1.引言2.主要特点3.成员函数4.使用实例 5.注意事项1.引言        在C++中,multimap是标准模板库(STL)中的一个关联容器,它存储键值对(key-valuepairs),并且允许键的重复。multimap内部通常通过红黑树(或其他平衡二叉搜索树)实现,这保证了元素按照键的顺序进行存储......
  • stm32单片机个人学习笔记10(TIM编码器接口)
    前言本篇文章属于stm32单片机(以下简称单片机)的学习笔记,来源于B站教学视频。下面是这位up主的视频链接。本文为个人学习笔记,只能做参考,细节方面建议观看视频,肯定受益匪浅。STM32入门教程-2023版细致讲解中文字幕_哔哩哔哩_bilibili一、编码器接口简介二、正交编码器 ......
  • 未发表的原创模型!三类典型需求响应负荷的标准化建模+共享储能提升灵活性(Matlab代码实
      ......
  • #STM32#定时器扫描按键消抖#按键控制LED灯亮灭#标准库
    一.机械按键抖动在按下按键后金属弹片会来回震动影响I/O口的电平变化,影响检测和判断操作。通常抖动时间为:5ms~10ms影响:在不加消除抖动的情况下按下按键LED灯可能会出现失灵的情况,因为这时的判断按键情况通常是判断电平的高低,由于电平不停的发转,所以呀很难判断此时是否是被......
  • 三维无限深势阱的标准解
    一、问题描述考虑一个粒子被限制在三维无限深方势阱中,势阱在三个方向上的边界分别为:\(0\leqx\leqL_x\)\(0\leqy\leqL_y\)\(0\leqz\leqL_z\)在势阱内部(即\(0\leqx\leqL_x\)、\(0\leqy\leqL_y\)、\(0\leqz\leqL_z\)),势能\(V=0\);而在势阱外部,势能......
  • ab压测的选项、示例和主要关注的指标意义以及ab压测问题Connection reset by peer (10
    一、ab压测的选项、示例和主要关注的指标意义1.ab压测的一些选项-nrequests    全部请求数-cconcurrency 并发数-ttimelimit   最传等待回应时间-ppostfile    POST数据文件-Tcontent-typePOSTContent-type-vverbosity   Howmuchtroubl......
  • JavaScript中的DOM和Timer(简单易用的基本操作)
    JavaScript中的DOM和Timer基本操作DOM操作传统的选择器选择器idvarelements=document.getElementById(id的名称);例如:varelements=document.getElementById("test");选择id为test的标签选择器classvarelements=document.getElementsByClassName(class的名称);......
  • 【转载】scipy.stats.norm.ppf —— 分位点函数(CDF的逆)(也被用作“标准偏差乘数”)
    原文地址:https://www.cnblogs.com/jiangkejie/p/15292260.htmlscipy.stats.norm.ppf()分位点函数(CDF的逆)(也被用作“标准偏差乘数”)即累计分布函数的逆函数(分位点函数,给出分位点返回对应的x值)。scipy.stats.norm.ppf(0.95,loc=0,scale=1)返回累积分布函数中概率等于0.95对应......
  • 【python-日期和时间处理】datetime模块基本使用
    1.获取datetime对象获取当前datetime对象方法:datetime.now(cls,tz=None)->datetime参数说明:tz:时区信息,不传该参数时,默认使用当地时区示例代码:now=datetime.now()print(now)#2023-01-0509:38:43.084062print(type(now))#datetime.datetime如果需......
  • 【python日期和时间处理】time模块基本使用
    1.time模块中三种时间格式时间戳time模块获取各种精度的时间戳importtimetimestamp=time.time()timestamp_s=int(time.time())#s精度timestamp_ms=int(time.time()*1000)#ms精度timestamp_us=int(time.time()*1000_000)#μs精度timestamp_ns=t......