STM32 TIM 定时器深度剖析:结构、时基、中断与应用开发(超形象详解)

文章目录

  • 定时器(TIM)
    • 定时器种类与分布
    • 定时器的基本结构
    • 时基单元
      • 时基单元基本结构
      • 计数器计数方向
      • 时基单元时钟来源计算
      • 寄存器预加载机制
    • 自制延时函数
      • 获取单片机当前时间
      • 实现延迟函数
      • 初始化定时器3的时基单元
      • 配置中断
      • 编写中断响应函数
      • 测试延迟函数

定时器(TIM)

定时器种类与分布

  • 定时器种类:单片机里定时器分高级、通用、基本三种,功能上高级定时器最全,通用定时器是在高级定时器基础上阉割部分功能,基本定时器则是在通用定时器基础上再阉割部分功能。
  • 分布情况:STM32F1 系列芯片最多有 14 个定时器,定时器 1 和 8 是高级定时器,定时器 6 和 7 是基本定时器,定时器 2 到 5 以及定时器 9 到 14 是通用定时器。实际使用芯片中有 1 个高级定时器(定时器 1)和 3 个通用定时器(定时器 2 - 4),学习编程一般以高级定时器 1 为例。

在这里插入图片描述

定时器的基本结构

时基单元,输出比较,输入捕获,从模式控制器四个部分。

在这里插入图片描述

时基单元

时基单元基本结构

  • 时钟源:时钟信号主要有两个来源,通常认为来自上一章学习的时钟树,一个为从模式控制器。
  • 预分频器:因输入时钟信号频率高,需用预分频器降频,其分频系数等于 PSC 的值加 1 。
  • 计数器 CNT:对经过分频后的脉冲信号计数,每来一个脉冲,计数器的值增加 1。
  • 自动重装寄存器 ARR:用于设置定时周期,定时周期的值等于 ARR 的值加 1。当计数器 CNT 的值增长到与 ARR 相等时,会发生溢出,然后从 0 开始重新计数。
  • 重复计数器 RCR:设置重复计数的次数。没有 RCR 时,计数器 CNT 每溢出一次产生一个 update 事件;加入 RCR 后,计数器 CNT 需要溢出 RCR + 1 次才产生一个 update 事件。
    在这里插入图片描述

和手表类似,手表有石英晶振提供时钟信号,还有其他电路装置进行降频,秒针相当于一个计数器,ARR为59,周期为60,RCR为0,每一个周期产生一个事件。

在这里插入图片描述

计数器计数方向

  • 上计数(count up):从 0 开始,左边每来一个脉冲,计数器 CNT 的值增加 1,直到增长到和自动重装计算器 ARR 相等时发生溢出,然后从 0 开始重新计数。
  • 下计数(count down):与上计数相反,从 ARR 开始计数,左边每来一个脉冲,计数器 CNT 的值减少 1,直到减少到 0 发生溢出,然后从 ARR 开始重新计数。
  • 中心对齐(center line):首先从 0 开始上计数到 ARR,然后转变成下计数,从 ARR 开始又计数到 0,完成一个定时周期。下计数和中心对齐用得较少,一般用上计数。

在这里插入图片描述

时基单元时钟来源计算

  • 分辨率和周期概念:类比手表,分辨率是计时的最小间隔,周期是转一圈所消耗的时间。对于定时器,计数器 CNT 每跳一下所消耗的时间是分辨率,从某点到计数器溢出是计数周期。
    在这里插入图片描述

  • 计算过程:以设置定时器 3 的 11 单元分辨率为 1 微秒,周期为 1 毫秒为例。先根据时钟树确定输入信号频率,当前配置下所有定时器时钟频率为 72 兆赫兹。要得到 1 微秒分辨率即 1 兆赫兹信号,设置预分频器 PSC 值为 71 ;要设置 1 毫秒周期,自动重装寄存器 AR 值为 999,重复计数器 RCR 值为 0。

    TIM_CLK是系统自动配置的,如果APB2和APB1的分频系数为1,TIM_CLK = PCLK2,如果其他系数 TIM_CLK = 2 * PCLK2,右面同理。

在这里插入图片描述

寄存器预加载机制

预加载机制,如果阴影为黑色,表示默认为开启,灰色表示默认为关闭。

  • 概念:向寄存器写值时,先写入影子寄存器,值不会立即生效,等计数器 CNT 溢出产生 update 事件时,影子寄存器的值才进入活动寄存器并生效,这种缓存机制叫寄存器预加载。

在这里插入图片描述

  • 作用:以自动重装寄存器 AR 为例,在定时器运行中改变 AR 值,不使用预加载机制会导致定时器跑飞,加入预加载机制后,可避免该问题,使计数周期正常过渡 。

    未使用预加载寄存器

在这里插入图片描述

使用了预加载寄存器

在这里插入图片描述

自制延时函数

使用定时器3和中断函数自制延时函数,因为使用的是while轮询等待所以还是会造成程序阻塞。

获取单片机当前时间

  • 定时器配置:假设时基单元输入时钟频率 72 兆赫兹,设置 PSC 值为 71 对输入时钟 72 分频,得到 1 兆赫兹时钟频率,周期 1 微秒;设置定时周期为 1000(999 + 1),即 1 毫秒;设置重复计数器 RCR 值为 0,使 update 事件频率 1 毫秒一次,激活 update 标志位产生中断。

  • 变量声明与作用:声明无符号 32 位整型变量 current tick ,赋初值 0,用于记录单片机当前时间(单位毫秒),变量前加 volatile 关键字(作用与中断有关,可自行百度学习)。

    在这里插入图片描述

  • 中断响应操作:中断每毫秒产生一次,在中断响应函数中让 current tick 值增加 1,从而记录单片机开机后的时间。
    在这里插入图片描述

实现延迟函数

  • 函数设计:定义延迟函数 APP delay,参数为要延迟的毫秒数。
  • 实现思路:用 current tick 获取当前时间,加上要延迟的时间得到延迟结束时间 expire time ,通过 while 循环等待当前时间超过延迟结束时间,函数结束即实现延迟。

在这里插入图片描述

初始化定时器3的时基单元

  • 第一步:使能时钟:定时器 3 在 APB1 总线上,调用 RCC_APB1PeriphClockCmd 开启其时钟。
  • 第二步:配置参数:学习 TIM_TimeBaseInit 编程接口,声明结构体变量 TM_TimeBaseInitTypeDef 并赋值,设置预分频器 PSC 值 71、周期值 999、计数方向为上计数、重复计数器 RCR 值 0,调用该接口完成参数配置。
  • 第三步:闭合开关:学习 TIM_Cmd 编程接口,用该接口闭合开关使定时器运行。

在这里插入图片描述

配置中断

  • 使能 update 中断:学习 TIM_ITConfig 编程接口,通过该接口闭合 update 标志位产生中断的开关。
  • 配置 NVIC 模块
    • 先在 main 方法开头配置中断优先级分组;
    • 再声明结构体变量 NVIC_InitTypeDef 并赋值,设置定时器 3 中断相关参数,调用 NVIC_Init 完成 NVIC 模块配置。

在这里插入图片描述

编写中断响应函数

  • 找到函数名:在启动文件的中断向量表中找到定时器 3 的中断响应函数 TIM3_IRQHandler ,复制到 main.c 文件进行实现。
  • 函数内容:先通过 TM_GetFlagStatus 检查是否由 update 标志位触发中断,若是则用 TM_ClearFlag 清除标志位,再让 current tick 值加 1。

在这里插入图片描述

测试延迟函数

  • 初始化板载 LED:写函数初始化板载 LED(PC13 引脚),开启 GPIOC 时钟,声明结构体变量并设置相关参数,初始化完成后关灯。
  • 编写闪灯程序:在 main 方法的 while 循环中编写闪灯代码,调用 APP delay 延迟函数,实现不同闪烁效果(如亮 500 毫秒灭 500 毫秒、两次短闪一次长闪等),编译下载代码到单片机测试,验证延迟函数可用 。

完整main.c代码

#include "stm32f10x.h"                  // Device headervolatile uint32_t currentTick = 0;
void App_delay(uint32_t ms);
void App_TIM3_BaseInit(void);
void App_GpioInit(void);
int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);App_TIM3_BaseInit();App_GpioInit();while(1){GPIO_ResetBits(GPIOC, GPIO_Pin_13);App_delay(100);GPIO_SetBits(GPIOC, GPIO_Pin_13);App_delay(100);GPIO_ResetBits(GPIOC, GPIO_Pin_13);App_delay(500);GPIO_SetBits(GPIOC, GPIO_Pin_13);App_delay(500);}
}
//自制延时函数逻辑
void App_delay(uint32_t ms)
{uint32_t extime = ms + currentTick;while(extime > currentTick);
}
//定时器3初始化
void App_TIM3_BaseInit(void)
{//开启定时器3的时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//配置时基单元参数TIM_TimeBaseInitTypeDef  TIM_TimeBaseInitStruct;TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStruct.TIM_Period = 999;TIM_TimeBaseInitStruct.TIM_Prescaler = 71;TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitStruct);//闭合时基单元开关TIM_Cmd(TIM3, ENABLE);//使能updateTIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);//配置NVIC模块NVIC_InitTypeDef NVIC_InitStruct;NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1;NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStruct);}
void TIM3_IRQHandler(void)
{//先判断是不是要的中断if(TIM_GetFlagStatus(TIM3, TIM_FLAG_Update) == SET){//将中断标志位清除TIM_ClearFlag(TIM3, TIM_FLAG_Update);//操作currentTick++;}
}
void App_GpioInit(void)
{RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);GPIO_InitTypeDef GPIO_InitStruct;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOC, &GPIO_InitStruct);
}

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

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

相关文章

Java使用minio上传整个目录下的所有内容

目录 1、添加相关配置 2、添加依赖 3、实现方法 1️⃣基础版: 2️⃣优化版(推荐使用): 3️⃣上传远程主机上的目录内容: 4️⃣直接上传远程主机中的目录内容 业务背景:需要需要minio进行上传指定目录下所有…

Python的分布式网络爬虫系统实现

1. 系统架构概述 一个典型的分布式网络爬虫系统通常包含以下几个核心组件: 1.主节点(Master Node): 任务调度:负责将抓取任务分配给各个工作节点。URL 管理:维护待抓取的 URL 队列和已抓取的 URL 集合&a…

AI工具的选择:Dify还是传统工具?

从纯技术视角出发,选择Dify还是传统开发工具需要基于六个核心维度进行理性决策。以下为结构化分析框架,附典型场景示例: 1. 开发效率 vs 控制力权衡矩阵 维度Dify优势场景传统工具优势场景迭代速度需求明确的标准CRUD(如后台管理…

2.3 TypeScript 非空断言操作符(后缀 !)详解

在 TypeScript 中,当你开启了严格的空值检查(strictNullChecks)后,变量如果可能是 null 或 undefined,就必须在使用前进行显式的判断。为了在某些场景下简化代码,TypeScript 提供了非空断言操作符&#xff…

深度学习:损失函数与激活函数全解析

目录 深度学习中常见的损失函数和激活函数详解引言一、损失函数详解1.1 损失函数的作用与分类1.2 回归任务损失函数1.2.1 均方误差(MSE)1.2.2 平均绝对误差(MAE) 1.3 分类任务损失函数1.3.1 交叉熵损失(Cross-Entropy&…

掌握 npm 核心操作:从安装到管理依赖的完整指南

图为开发者正在终端操作npm命令,图片来源:Unsplash 作为 Node.js 生态的基石,npm(Node Package Manager)是每位开发者必须精通的工具。每天有超过 1700 万个项目通过 npm 共享代码,其重要性不言而喻。本文…

Elasticsearch的运维

Elasticsearch 运维工作详解:从基础保障到性能优化 Elasticsearch(简称 ES)作为分布式搜索和分析引擎,其运维工作需要兼顾集群稳定性、性能效率及数据安全。以下从核心运维模块展开说明,结合实践场景提供可落地的方案…

国产三维CAD皇冠CAD(CrownCAD)建模教程:汽车电池

在线解读『汽车电池』的三维建模流程,讲解3D草图、保存实体、拉伸凸台/基体、设置外观等操作技巧,一起和皇冠CAD(CrownCAD)学习制作步骤吧! 汽车电池(通常指铅酸蓄电池或锂离子电池)是车辆电气系…

深入理解 JDK、JRE 和 JVM 的区别

在 Java 中,JDK、JRE 和 JVM 是非常重要的概念,它们各自扮演着不同的角色,却又紧密相连。今天,就让我们来详细探讨一下它们之间的区别。 一、JVM JVM 即 Java 虚拟机,它是整个 Java 技术体系的核心。JVM 提供了 Java…

云电脑显卡性能终极对决:ToDesk云电脑/顺网云/海马云,谁才是4K游戏之王?

一、引言 1.1 云电脑的算力革命 云电脑与传统PC的算力供给差异 传统PC的算力构建依赖用户一次性配置本地硬件,特别是CPU与显卡(GPU)。而在高性能计算和游戏图形渲染等任务中,GPU的能力往往成为决定体验上限的核心因素。随着游戏分…

撤销Conda初始化

在安装miniconda3的过程中,最后系统会出现这一行提示用户可以选择自动初始化,这样的话,系统每次启动就会自动启动基础(base)环境。 但是我们也可以通过 conda init --reverse $shell 来撤销 Conda 的初始化设置。这将恢…

Flask-SQLAlchemy数据库查询:query

1、为什么可以用 模型类.query 来查询数据库? 在 Flask 中使用 SQLAlchemy ORM 时,所有继承自 db.Model 的模型类都会自动获得一个 query 属性。 其本质是 db.session.query(模型类) 的快捷方式,无需显式操作 db.session。 代码示例&#…

【免费】【无需登录/关注】度分秒转换在线工具

UVE Toolbox 功能概述 这是一个用于地理坐标转换的在线工具,支持两种转换模式: 十进制度 → 度分秒 度分秒 → 十进制度 使用方法 十进制度转度分秒 在"经度"输入框中输入十进制度格式的经度值(例如:121.46694&am…

怎么判断一个Android APP使用了React Native 这个跨端框架

要判断一个 Android 应用是否使用了 React Native 框架,可以通过以下方法逐步验证: 一、安装包结构分析 1. 解压 APK 将 .apk 文件重命名为 .zip 并解压,检查以下特征文件: • assets/index.android.bundle: React Na…

Pluto实验报告——基于2ASK的简易的通信系统

一、实验目的 1. 熟悉并掌握PLUTO SDR 主动学习模块的使用; 2.通过matlab 编码与adalm pluto 相配合达成一个简易的通信系统,并能 够传输一些较为简单的信息。 二、实验原理 2ASK 调制原理: 振幅键控是指利用载波的振幅变化来传递数字基带信…

Ubuntu 24-部署FTP和自定义用户

目录 一、 安装 vsftpd 二、创建 FTP 数据目录 三、创建 FTP 用户 四、配置 vsftpd 五、重启 vsftpd 服务 六、增加新用户脚本 一、 安装 vsftpd sudo apt update sudo apt install vsftpd -y 二、创建 FTP 数据目录 sudo mkdir -p /data/ftp sudo chown nobody:nogrou…

MySQL问题:什么是MySQL的中的最左匹配原则?

是指在复合索引中,查询条件需要按照索引列的顺序从最左侧列开始依次匹配。只有查询条件中的列按照索引的最左边列开始进行匹配,索引才能被有效使用,但有时虽然不是正常顺序,由于MySQL中存在优化器,会自动调整顺序&…

2025软考软件设计师题目

选择题(综合题) 确定得分的 1、Linux外设目录是什么 /dev。存储磁盘的目录 2、Linux外设sdc类型设备属于什么 scsi hard disk。根据第一个字母s盲猜的 3、计算机中让程序计数器PC不能指向当前运行程序的技术是 流水线。根据流水线的原理 4、Python程…

Deep Evidential Regression

摘要 翻译: 确定性神经网络(NNs)正日益部署在安全关键领域,其中校准良好、鲁棒且高效的不确定性度量至关重要。本文提出一种新颖方法,用于训练非贝叶斯神经网络以同时估计连续目标值及其关联证据,从而学习…

每天掌握一个Linux命令 - sqlite3

Linux 命令工具 sqlite3 使用指南 一、工具概述 sqlite3 是 SQLite 数据库的命令行工具,用于在 Linux 系统中直接操作 SQLite 数据库(轻量级、无服务器、嵌入式关系型数据库)。 核心特点: 无需安装数据库服务,直接通…