当前位置: 首页 > news >正文

STM32--TIM定时器(1)

文章目录

  • TIM简介
    • 定时器类型
  • 通用定时器
  • 预分频器时序
  • 计数器时序
  • 定时中断基本结构
  • TIM内部中断工程
  • TIM外部中断工程

TIM简介

STM32的TIM(定时器)是一种非常常用的外设,用于实现各种定时和计数功能。它是基于时钟信号进行计数,并在计数值达到设定值时触发中断,执行相应的操作

定时器类型

一般来说,STM32中有三类定时器:
在这里插入图片描述
在我们这款STM32F03C9T6有4种定时器资源:TIM1,TIM2,TIM3,TIM4;

对于定时器,类型越高级,拥有的功能越多,且向下兼容;
我们将以通用定时器进行讲解

通用定时器

通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成
它适用于多种场合,包括测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。
使用定时器预分频器和RCC时钟控制器预分频器,脉冲信号长度和波形周期可以在几个微妙到几个毫秒间调整。
每个定时器都是完全独立的,没有互相共享任何资源。它们可以同步操作。
在这里插入图片描述
这是通用定时器的总框图,我将会分为几部分进行讲解。

在这里插入图片描述
这是定时器最基本的结构,通过RCC内部时钟产生的脉冲频率通向预分频器,频率分频后到计数器,当达到自动重装载寄存器的值,将会发出信号,或者触发中断

RCC的TIMxCLK会产生一个72MHz的脉冲频率;
在这里插入图片描述
这一部分称为时基单元,是TIM计时器最主要的计数计时结构。

PSC预分频器会将72MHZ进行分频,可以按1到65536之间的任意值分频;将输入频率除以预分频器值就得到分频结果;

通过频率会在计数器中计数,通过传输的频率的上升沿,计数器将加一
计数器取值范围为0到65535;所以计数的快慢由输入频率决定;
对于通用计数器来说,计数器是有多种模式进行计数的。
向上计数模式:计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。
向下计数模式:计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。
中央对齐模式:计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器
溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

自动重装载寄存器相当就是给计数器一个周期值,当计数器达到这个值就会产生中断,并清零计数器;计数器溢出中断后,会产生更新中断,传到NVIC中,最后传到CPU,那么定时器就能产生中断了。也会产生更新事件,它会触发内部其他电路的工作。

在这里插入图片描述
这部分,是定时器时钟频率的来源,在通用定时器中,不止有内部时钟,还有外部时钟。
第一个外部时钟TIMx_ETR,如果在引脚上默认有该功能,就能直接使用,作为外部时钟的连接引脚;
在这里插入图片描述
传输进来的方波信号会通过极性选择,边沿检测,滤波等进行整形,处理掉一些毛刺;滤波后的信号兵分两路,第一路是走到ETRF,通过触发控制器走到复位使能,这种走法称为“外部时钟模式2”。(TRIGO是映射功能,能够从主模式触发DAC)。第二路是TRGI,主要用作触发使用的,可以走到从模式;当然也可以走复位,使能那里,那么这样的外部时钟称为“外部时钟模式1”。

第二个的来源就是ITR,TRIGO可以通向其他定时器,其他定时器就是通过ITR引脚来连接的。
在这里插入图片描述
这是内部定时器连接的方式。可以允许4种定时器进行连接到定时器上,但是只允许一个定时器连接着一个定时器。

第三个一个是TIIF_ED,这里连接着输入捕获单元的CH1,ED为Edge,边沿的意思,触发方式上升沿和下降沿都有效。
在这里插入图片描述

最后一个是TI1FP1和TI2FP2
在这里插入图片描述
后续将会讲解。
在这里插入图片描述
下边的,左半部分为输入捕获电路,右半部分为输出比较部分,每部分都有4个通道可以进入,且输入和输出共用一个寄存器,意味着不能边输入边输出,具体功能将会后续讲解。

预分频器时序

在这里插入图片描述
这是一个预分频器从1变到2的时序图。
CK_PSC是时钟频率,一般都为72MHZ;
CNT_EN是计时器使能,只有在使能高电平状态下,才能运行。
CK_CNT是计时器时钟,它既是预分频器的时钟输出,也是计数器的时钟输入;当使能为高电平时,CNT开始运行,前半段频率跟时钟一样,后半段预分频器从1变到2,CNT让定时器上升沿减半,即一个周期有效,一个周期无效(保持低电平)。
在计时器时钟的驱动下,计时器寄存器也不断增加,当达到FC时(与自动重转载寄存器的值一样)将会从0开始;
更新事件UEV,当计数器寄存器到FC时,更新事件将会触发。
下面三个时序将一起看,这是预分频控制寄存器的缓冲机制,我们写入的值会到预分频控制寄存器上,当在计数器未归零之前写入时,为了保持完整性,将会在更新事件后才会进行分频。所以到预分频缓冲器上才是所读的正确结果,而预分频计数器会在1时保持定时器时钟为低电平,为0时保持原先状态。

计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)
PSC相对我们输入者来说,就是0开始的,当对于PSC来说,是从1开始的。就像一块蛋糕,不切时它就是1份完整的,切一刀时,就会被分成两份。

计数器时序

在这里插入图片描述
大体来说与预分频器一致,当计数器寄存器满时,将会使计数器溢出,更新事件发生,更新中断标志。

计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)
= CK_PSC / (PSC + 1) / (ARR + 1)

定时中断基本结构

对于我们来说,由于有库函数的提供,不需要管哪些寄存器,我们需要了解一些代码逻辑结构。
在这里插入图片描述
通过外部引脚GPIO就可连接外部时钟,然后选择时钟模式,接着对时基单元初始化,接上NVIC即可。

TIM内部中断工程

连接方式:
在这里插入图片描述

OLED函数可以点击连接

该工程将会实现走秒的例子。
Timer.h

#ifndef __TIMER_H__
#define __TIMER_H__void Timer_Init();#endif

Timer.c

#include "stm32f10x.h"                  // Device headervoid Timer_Init()
{//开启APB1外设开关RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//配置TIM2为内部时钟TIM_InternalClockConfig(TIM2);//时钟结构体初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //划分TIM2TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计时器模式,上升沿计时TIM_TimeBaseInitStructure.TIM_Period=10000-1; //自动加载寄存器周期值TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1; //预分频值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //指定重复计时器的值,这里不用到TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//清除标志位TIM_ClearFlag(TIM2, TIM_FLAG_Update);//启用TIM2中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//配置优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC初始化NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);//启用TIM2外设控制TIM_Cmd(TIM2,ENABLE);
}

对于内部时钟,没有外部引脚的使用,记住TIM所在总线是APB1,先开启外设开关,接着配置TIM2的内部时钟,然后对时基单元结构体成员进行初始化,对于预分频器值,通过公式可知需要-1才能达到我们想要的数字,重复计时器是高级计时器的操作,这里不需要用到。
在这里插入图片描述
在初始化完将会生成一个更新事件,立即重新加载预分频和计时器的计算。在更新一个事件后,同时也会产生中断标志,为了让计时时从0开始,就采用了清除标志的函数。
最后记得启用TIM2的外设,否则无效。

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
#include "OLED.h"
#include "Timer.h"uint16_t Count;
int main()
{OLED_Init();Timer_Init();while(1){OLED_ShowNum(1,1,Count,4);}
}//中断函数
void TIM2_IRQHandler()
{
//表示已经触发中断了if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){Count++;//中断挂起位,中断结束后需要将中断位挂起,让下一个能进入中断TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}

TIM外部中断工程

接线方式:
在这里插入图片描述
通过对射式红外传感器的电平变化作为CNT的触发条件,然后通过10次的电平变化,让计时器溢出进1;

Timer.h

#ifndef __TIMER_H__
#define __TIMER_H__void Timer_Init();#endif

Timer.c

#include "stm32f10x.h"                  // Device headervoid Timer_Init()
{//开启APB1外设开关RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin=GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&GPIO_InitStructure);//配置TIM2为外部时钟模式2TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);//时钟结构体初始化TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; //表示不分频TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //计时器模式TIM_TimeBaseInitStructure.TIM_Period=10-1; //自动加载寄存器周期值TIM_TimeBaseInitStructure.TIM_Prescaler=1-1; //预分频值TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0; //指定重复计时器的值,这里不用到TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//TIM_ClearFlag(TIM2, TIM_FLAG_Update);//启用TIM2中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);//配置优先级分组NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC初始化NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;NVIC_Init(&NVIC_InitStructure);//启用TIM2外设控制TIM_Cmd(TIM2,ENABLE);
}

外部时钟模式2:
TIM_ExtTRGPrescaler:外部触发预分频器
TIM_ExtTRGPolarity_NonInverted:触发极性为上升沿或高电平;
ExtTRGFilter:最后一个参数,表示滤波频率高低,可选范围0x00 and 0x0F;一般来说,滤波频率越高,毛刺与不规则信号处理的越干净。

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "Buzzer.h"
#include "LightSensor.h"
#include "OLED.h"
#include "Timer.h"uint16_t Count;
int main()
{OLED_Init();Timer_Init();while(1){OLED_ShowNum(1,1,Count,4);OLED_ShowNum(2,1,TIM_GetCounter(TIM2),5);}
}void TIM2_IRQHandler()
{if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){Count++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}

相关文章:

STM32--TIM定时器(1)

文章目录 TIM简介定时器类型 通用定时器预分频器时序计数器时序定时中断基本结构TIM内部中断工程TIM外部中断工程 TIM简介 STM32的TIM(定时器)是一种非常常用的外设,用于实现各种定时和计数功能。它是基于时钟信号进行计数,并在计…...

Android取证——基础知识

目录 一、安卓系统版本 二、安装操作系统UI 三、鉴权码 1.IMEI(手机序列号) 2.ICCID...

【学习心得】安装cuda/cudann和pytorch

一、查看驱动信息 # 进入CMD输入命令 nvidia-smi 也可以右下角图标打开NVIDIA 设置进行查看 二、下载安装CUDA 1、下载 下载地址 https://developer.nvidia.com/ 2、安装 推荐自定义安装。建议只勾选Cuda,只安装这一个就好,以免报错安装失败。 3、验证…...

中电金信通过KCSP认证 云原生能力获权威认可

中电金信通过KCSP(Kubernetes Certified Service Provider)认证,正式成为CNCF(云原生计算基金会)官方认证的 Kubernetes 服务提供商。 Kubernetes是容器管理编排引擎,底层实现为容器技术,是云原…...

【Spring】Bean的实例化

1、简介 在容器中的Bean要实例化为对象有三种方式 1、构造方法 2、静态工厂 3、实例工厂 4、实现工厂接口 2、构造方法 构造方法实例化Bean即是直接通过构造方法创建对象 <bean id"bookDao" class"com.wn.spring.dao.impl.BookDaoImpl"/> 当不存在…...

2023牛客暑期多校训练营8-C Clamped Sequence II

2023牛客暑期多校训练营8-C Clamped Sequence II https://ac.nowcoder.com/acm/contest/57362/C 文章目录 2023牛客暑期多校训练营8-C Clamped Sequence II题意解题思路代码 题意 解题思路 先考虑不加紧密度的情况&#xff0c;要支持单点修改&#xff0c;整体查询&#xff0…...

【GitLab私有仓库】如何在Linux上用Gitlab搭建自己的私有库并配置cpolar内网穿透?

文章目录 前言1. 下载Gitlab2. 安装Gitlab3. 启动Gitlab4. 安装cpolar5. 创建隧道配置访问地址6. 固定GitLab访问地址6.1 保留二级子域名6.2 配置二级子域名 7. 测试访问二级子域名 前言 GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用Git作为代码管理工具&#xf…...

企业计算机服务器遭到了locked勒索病毒攻击如何解决,勒索病毒解密

网络技术的不断发展&#xff0c;也为网络安全埋下了隐患&#xff0c;近期&#xff0c;我们收到很多企业的求助&#xff0c;企业的计算机服务器遭到了locked勒索病毒的攻击&#xff0c;导致企业的财务系统内的所有数据被加密无法读取&#xff0c;严重影响了企业的正常运行。最近…...

Redis哨兵模式搭建

Redis主从复制搭建 Redis虽然拥有非常高的性能&#xff0c;但是在实际的生产环境中&#xff0c;使用单机模式还是会产生不少问题的&#xff0c;比如说容易出现 单机故障&#xff0c;容量瓶颈&#xff0c;以及QPS瓶颈等问题。通常环境下&#xff0c;主从复制、哨兵模式、Redis…...

大语言模型控制生成的过程Trick:自定义LogitsProcessor实践

前言 在大模型的生成过程中&#xff0c;部分原生的大语言模型未经过特殊的对齐训练&#xff0c;往往会“胡说八道”的生成一些敏感词语等用户不想生成的词语&#xff0c;最简单粗暴的方式就是在大模型生成的文本之后&#xff0c;添加敏感词库等规则手段进行敏感词过滤&#xf…...

Docker容器:docker的资源控制及docker数据管理

文章目录 一.docker的资源控制1.CPU 资源控制1.1 资源控制工具1.2 cgroups有四大功能1.3 设置CPU使用率上限1.4 进行CPU压力测试1.5 设置50%的比例分配CPU使用时间上限1.6 设置CPU资源占用比&#xff08;设置多个容器时才有效&#xff09;1.6.1 两个容器测试cpu1.6.2 设置容器绑…...

从零开始打造家装预约咨询小程序

在如今互联网高度发达的时代&#xff0c;家装行业也逐渐意识到了线上渠道的重要性。为了更好地服务客户&#xff0c;提高用户体验&#xff0c;越来越多的家装公司开始寻找合适的小程序制作平台。本文将向大家介绍如何使用第三方制作平台&#xff0c;如乔拓云网&#xff0c;打造…...

es线上处理命令记录

常用命令 搜索 GET _search {"query": {"match_all": {}} }获取全部模版 GET _index_template GET _index_template/yst_crawler_template获取全部索引 GET /_cat/indices?v 获取当前mapping GET /yst_crawler/_mapping创建一个mapping PUT /yst_c…...

mysql 在nodejs中的简单使用(增删改查)

一 、封装SQL查询请求链接 const mysql require(mysql) //创建开发工具数据库链接池 const pool mysql.createPool({host: 192.168.1.133,user: user_name, password: 123456,database: database_name,port: 3306,connectionLimit: 50 // 限制连接数 });// sql&#xff1a;查…...

1.MySQL数据库的基本操作

数据库操作过程&#xff1a; 1.用户在客户端输入 SQL 2.客户端会把 SQL 通过网络发送给服务器 3.服务器执行这个 SQL,把结果返回给客户端 4.客户端收到结果,显示到界面上 数据库的操作 这里的数据库不是代表一个软件&#xff0c;而是代表一个数据集合。 显示当前的数据库 …...

Zabbix-6.4.4 邮箱告警SMS告警配置

目录 ​------------------------- # 邮箱告警 ---------------------------------- 1.安装mailx与postfix软件包 2.修改mailx配置文件 3. 创建文件夹 4. 编写mail-send.sh脚本 5. 将该脚本赋予执行权限 6. 进入web界面进行设置—> Alerts —> Media Types 7. 添…...

网络安全 Day30-运维安全项目-容器架构上

容器架构上 1. 什么是容器2. 容器 vs 虚拟机(化) :star::star:3. Docker极速上手指南1&#xff09;使用rpm包安装docker2) docker下载镜像加速的配置3) 载入镜像大礼包&#xff08;老师资料包中有&#xff09; 4. Docker使用案例1&#xff09; 案例01&#xff1a;:star::star::…...

深入理解设计模式-创建型之单例模式

为什么要使用单例 1、表示全局唯一 如果有些数据在系统中应该且只能保存一份&#xff0c;那就应该设计为单例类。 如&#xff1a;配置类&#xff1a;在系统中&#xff0c;我们只有一个配置文件&#xff0c;当配置文件被加载到内存之后&#xff0c;应该被映射为一个唯一的【配…...

Vue中路由缓存问题及解决方法

一.问题 Vue Router 允许你在你的应用中创建多个视图&#xff0c;并根据路由来动态切换这些视图。默认情况下&#xff0c;当你从一个路由切换到另一个路由时&#xff0c;Vue Router 会销毁前一个路由的组件实例并创建新的组件实例。然而&#xff0c;有时候你可能希望保持一些页…...

Linux与bash(基础内容一)

一、常见的linux命令&#xff1a; 1、文件&#xff1a; &#xff08;1&#xff09;常见的文件命令&#xff1a; &#xff08;2&#xff09;文件属性&#xff1a; &#xff08;3&#xff09;修改文件属性&#xff1a; 查看文件的属性&#xff1a; ls -l 查看文件的属性 ls …...

java_网络服务相关_gateway_nacos_feign区别联系

1. spring-cloud-starter-gateway 作用&#xff1a;作为微服务架构的网关&#xff0c;统一入口&#xff0c;处理所有外部请求。 核心能力&#xff1a; 路由转发&#xff08;基于路径、服务名等&#xff09;过滤器&#xff08;鉴权、限流、日志、Header 处理&#xff09;支持负…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

如何应对敏捷转型中的团队阻力

应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中&#xff0c;明确沟通敏捷转型目的尤为关键&#xff0c;团队成员只有清晰理解转型背后的原因和利益&#xff0c;才能降低对变化的…...

Ubuntu系统复制(U盘-电脑硬盘)

所需环境 电脑自带硬盘&#xff1a;1块 (1T) U盘1&#xff1a;Ubuntu系统引导盘&#xff08;用于“U盘2”复制到“电脑自带硬盘”&#xff09; U盘2&#xff1a;Ubuntu系统盘&#xff08;1T&#xff0c;用于被复制&#xff09; &#xff01;&#xff01;&#xff01;建议“电脑…...

Docker拉取MySQL后数据库连接失败的解决方案

在使用Docker部署MySQL时&#xff0c;拉取并启动容器后&#xff0c;有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致&#xff0c;包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因&#xff0c;并提供解决方案。 一、确认MySQL容器的运行状态 …...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...