TIM定时器(标准库)

news2024/11/25 5:03:28

目录

一. 前言

二. 定时器的框图

三. 定时中断的基本结构

 四. 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更新事件的中断标志位
															//中断标志位必须清除
															//否则中断将连续不断地触发,导致主程序卡死
	}
}

五. 最终现象展示

 

 

        

        

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2211652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【LeetCode】708. 循环有序列表的插入

目录 一、题目二、解法完整代码 一、题目 给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素 insertVal ,使这个列表仍然是循环非降序的。 给定的可以是这个列表中任意一个顶点的指针,并不一定是这个列表中最小元素的…

2024免费mac苹果电脑清理垃圾软件CleanMyMac X4.15.8

对于苹果电脑用户来说,设备上积累的垃圾文件可能会导致存储空间变得紧张,影响电脑的性能和使用体验。尤其是那些经常下载和安装新应用、编辑视频或处理大量照片的用户,更容易感受到存储空间的压力。面对这种情况,寻找一种有效的苹…

springboot3使用Excel导入数据库数据

一、导入依赖 <!-- https://mvnrepository.com/artifact/org.apache.poi/poi-ooxml --><dependency><groupId>org.apache.poi</groupId><artifactId>poi-ooxml</artifactId><version>5.3.0</version></dependency> 二、…

Xilinx远程固件升级(二)——STARTUPE2原语的使用

通过&#xff08;一&#xff09;可以看出&#xff0c;对于远程固件升级实际上是通过调用flash不同区域的bit实现&#xff0c;通过golden image和update image共同保障了系统的稳定性。在项目中如果将flash的时钟直接绑定FPGA后进行约束&#xff0c;在综合编译时是无法通过的。这…

Spark:DataFrame介绍及使用

1. DataFrame详解 DataFrame是基于RDD进行封装的结构化数据类型&#xff0c;增加了schema元数据&#xff0c;最终DataFrame类型在计算时&#xff0c;还是转为rdd计算。DataFrame的结构化数据有Row&#xff08;行数据&#xff09;和schema元数据构成。 Row 类型 表示一行数据 …

MySQL 8.4修改初始化后的默认密码

MySQL 8.4修改初始化后的默认密码 &#xff08;1&#xff09;初始化mysql&#xff1a; mysqld --initialize --console &#xff08;2&#xff09;之后,mysql会生成一个默认复杂的密码&#xff0c;如果打算修改这个密码&#xff0c;可以先用旧密码登录&#xff1a; mysql -u…

Redis set类型 zset类型

set类型 类型介绍 集合类型也是保存多个字符串类型的元素的&#xff0c;但和列表类型不同的是&#xff0c;集合中 1&#xff09;元素之间是⽆序 的 2&#xff09;元素不允许重复 ⼀个集合中最多可以存储 个元素。Redis 除了⽀持 集合内的增删查改操作&#xff0c;同时还⽀持多…

【图书推荐】《R语言医学数据分析实践》

本书重点 梅俏、卢龙、丁健、张晟、黄龙、胡志坚、张琼瑶、林志刚等业内专家联袂推荐。 以公共医学数据为例&#xff0c;精选大量的实用案例&#xff0c;深入浅出地介绍统计建模分析方法。 帮助读者解决医学数据分析中遇到的实际问题。 通过实际操作引导读者入门科研论文数…

生信分析流程:从数据准备到结果解释的完整指南

介绍 生物信息学&#xff08;生信&#xff09;分析是一个复杂的过程&#xff0c;涉及从数据准备到结果解释的多个步骤。随着高通量测序技术的发展和生物数据的迅猛增长&#xff0c;了解和掌握生信分析的标准流程变得尤为重要。这不仅有助于提高分析的准确性&#xff0c;还能优…

HarmonyOS NEXT 应用开发实战(五、页面的生命周期及使用介绍)

HarmonyOS NEXT是华为推出的最新操作系统&#xff0c;arkUI是其提供的用户界面框架。arkUI的页面生命周期管理对于开发者来说非常重要&#xff0c;因为它涉及到页面的创建、显示、隐藏、销毁等各个阶段。以下是arkUI页面生命周期的介绍及使用举例。 页面的生命周期的作用 页面…

7-I2C与AHT20温湿度传感器

I2C与AHT20温湿度传感器 嵌入式领域另一种常见的通信IIC通信&#xff0c;并用其与AHT20传感器进行交互&#xff0c;获取房间的温度与湿度。 I2C有一条用于传递数据的数据线称为SDA&#xff08;Serial Data&#xff09;&#xff0c;另一条是用于提供同步时钟脉冲的时钟线SCL&am…

看图识微分与导数概念。

可建立如草图所示的局部坐标系。增量Δydy余项是草图中曲线的方程&#xff0c;微分dyydx&#xff08;是关于dx的一次函数&#xff09;是草图中切线的方程。草图形象直观地显示曲线Δy不切线dy。

安全可靠测评结果公告(2024年第1号)

大家可以选择对应的数据库&#xff0c;中央处理器&#xff0c;供参考&#xff1b;尤其是 水资源安可系统 智慧农业安可系统 智慧水利安可系统、智慧水务安可系统&#xff0c;企业安可系统 等参考使用

# 在执行 rpm 卸载软件使用 nodeps 参数时,报错 error: package nodeps is not installed 分析

在执行 rpm 卸载软件使用 nodeps 参数时&#xff0c;报错 error: package nodeps is not installed 分析 一、问题描述&#xff1a; 在执行 rpm 卸载软件使用 nodeps 参数时&#xff0c;报错 error: package nodeps is not installed 如下图&#xff1a; 二、报错分析&…

Java项目分层思路

Java项目分层思路 一、前言二、了解常见的术语1. 应用开发中使用的术语2. 建模和架构设计层面术语总结 三、如何划分1. 单个module2. 多个module 一、前言 每个人、每个开发团队的规范习惯都不太一样&#xff0c;没有固定标准&#xff0c;合适的才是最好的。 二、了解常见的术…

Python Django 查询集的延迟加载特性

Django 查询集的延迟加载特性 一、引言 在 Django 的开发过程中&#xff0c;查询集&#xff08;QuerySet&#xff09;是我们与数据库进行交互的重要工具。查询集提供了一种高效的方式来检索和操作数据库中的数据&#xff0c;且能够进行懒加载&#xff08;Lazy Loading&#x…

Gin框架教程02:AsciiJSON

什么是 AsciiJSON&#xff1f; AsciiJSON 是 Gin 框架中的一个方法&#xff0c;用于生成仅包含 ASCII 字符的 JSON。对于非 ASCII 字符&#xff08;例如汉字、特殊符号&#xff09;&#xff0c;AsciiJSON 会将其转义为 Unicode 表示&#xff08;如 \uXXXX&#xff09;&#xff…

使用CSS+SVG实现加载动画

使用CSSSVG实现加载动画 效果展示 CSS知识点 SVG元素使用SVG相关CSS属性运用 整体页面布局 <section><div class"box"><div class"loader"><svg><circle cx"40" cy"40" r"40"></circl…

vue从0开始的项目搭建(含环境配置)

一、环境准备 下载node.js 检查node.js版本 替换npm下载源 1.下载node.js: Node.js — 在任何地方运行 JavaScript (nodejs.org) 2.查看版本: windowsr输入cmd进入输入node -v命令查看版本号是否出现确认是否安装 2.替换npm下载源: npm config set registry https://reg…

深入Semantic Kernel:插件开发与实践应用(进阶篇)

文章目录 一、引言二、开发Semantic Kernel插件三、实战3.1 时间信息插件3.2 小部件工厂插件3.3 初始化Semantic Kernel实例3.4 四个实战示例3.4.1 模型幻觉3.4.2 给模型提供时间信息3.4.3 AI自动调用函数3.4.4 AI自动调用和使用枚举 四、结论 一、引言 在上一篇入门文章《探索…