【STM32开发之寄存器版】(六)-通用定时器中断

一、前言

STM32定时器分类

STM32103ZET6具备8个定时器TIMx(x = 1,2,...,8)。其中,TIM1和TIM8为高级定时器,TIM2-TIM6为通用定时器,TIM6和TIM7为基本定时器,本文将以TIM3通用定时器为例,分析STM32定时器工作的底层寄存器原理。

STM32通用定时器简介

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

本文DEMO目标

本次DEMO将使用STM32F103ZET6的定时器TIM3实现DS1的翻转(定时器中断),在主函数用DS0的翻转来提示程序正在运行。

二、通用定时器的主要功能

通用TIMx (TIM2、TIM3、TIM4和TIM5)定时器功能包括:
● 16位向上、向下、向上/向下自动装载计数器
● 16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为  1~65536  之间的任意 数值
● 4个独立通道:
─ 输入捕获
─ 输出比较
─ PWM生成(边缘或中间对齐模式)
─ 单脉冲模式输出
● 使用外部信号控制定时器和定时器互连的同步电路
● 如下事件发生时产生中断/DMA:
─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
─ 输入捕获
─ 输出比较
● 支持针对定位的增量(正交)编码器和霍尔传感器电路
● 触发输入作为外部时钟或者按周期的电流管理

三、时钟树解析

定时器的时钟来源一共有以下4个:

  • 内部时钟(CK_INT)
  • 外部时钟模式 1:外部输入脚(TIx)
  • 外部时钟模式 2:外部触发输入(ETR)
  • 内部触发输入(ITRx):使用 A 定时器作为 B 定时器的预分频器(A 为 B 提供时钟)。

这些时钟,具体选择哪个可以通过 TIMx_SMCR 寄存器的相关位来设置。这里的 CK_INT时钟是从 APB1 倍频的来的,除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1的时钟。

本文选用CK_INT作为定时器时钟来源。

系统时钟为72MHz,AHB不分频,APB1后最大频率为36MHz,故APB1作2分频,故TIM3的时钟是APB1时钟的2倍,即TIM3CLK=72MHz。具体时钟树解析如下所示:

四、寄存器介绍

对通用定时器TIM3的控制主要涉及以下寄存器:

寄存器作用
TIMx_CR1控制寄存器1
TIMx_DIERDMA/中断使能寄存器
TIMx_PSC预分频器
TIMx_SMCR从模式控制寄存器
TIMx_CNT计数器
TIMx_ARR自动重装载寄存器
TIMx_SR状态寄存器

下面将对这些寄存器进行一一介绍。

4.1 TIMx_CR1控制寄存器1

《STM32中文手册》对TIMx_CR1寄存器的描述如下:

我们仅需要关注其第7位和第0位,第7位为自动重装载允许位,具体作用见4.6节。第0位为计数器的使能位,该位必须置1,才能让定时器开始计数

4.2 TIMx_DIER DMA/中断使能寄存器

《STM32中文手册》对TIMx_DIER寄存器的描述如下:

我们仅需关注其第0位,该位为允许更新中断位,该位需要置1,才能允许更新事件所产生的中断。

4.3 TIMx_PSC预分频器

《STM32中文手册》对TIMx_PSC寄存器的描述如下:

该寄存器用于设计时钟分频,然后提供给计数器,作为计数器的时钟,该寄存器中值的范围是0-65535,按照公式fCK_CNT=fCK_PSC/(PSC[15:0]+1)。分频系数的范围为1-65536,按照前文对时钟树的解析,这里的fCK_PSC为72MHz。

4.4 TIMx_SMCR从模式控制寄存器

《STM32中文手册》对TIMx_SMCR寄存器的描述如下:

我们仅需关注该寄存器的位[2:0],即SMS从模式选择,将其设置为000,即关闭从模式,此时如果CEN=1,则预分频器直接由内部时钟驱动(CK_INT)。由于该寄存器的复位值为0X0000,故无需更改此寄存器的值。

4.5 TIMx_CNT计数器

《STM32中文手册》对TIMx_CNT寄存器的描述如下:

该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。定时器的超时时间由下式计算:

Time = CNT / fCK_CNT

其中:

Time为超时时间,CNT为TIMx_CNT的计数值,fCK_CNT为定时器预分频频率。

4.6 TIMx_ARR自动重装载寄存器

《STM32中文手册》对TIMx_ARR寄存器的描述如下:

该寄存器包含了将要传送至实际的自动重装载寄存器的数值。该寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《STM32中文参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。根据 TIMx_CR1寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2 者是连通的;而 APRE=1 时,在每一次更新事件(UEV)时,才把预装在寄存器的内容传送到影子寄存器。我们将APRE值设置为0(复位时就是0,不用改)

4.7 TIMx_SR状态寄存器

《STM32中文手册》对TIMx_SR寄存器的描述如下:

我们只关注其第0位,该位为更新中断标记。当计数器 CNT 被重新初始化的时候,产生更新中断标记,通过这个中断标志位,就可以知道产生中断的类型。当该位为1时,表示中断产生,需要在中断服务函数中用软件对该位清0。

五、程序设计

该DEMO程序主要分为三个部分:定时器3初始化程序,定时器3中断服务程序以及轮询主函数。下面进行一一介绍。

5.1 定时器3初始化程序

该部分程序在HARDWARE/timer.c/TIM3_Int_Init(),主要作用是TIM3时钟使能、设置定时器超时值、允许中断更新、使能定时器3,并注册定时器3的中断,具体代码如下所示:

//通用定时器3中断初始化
//这里时钟选择为APB1的2倍,而APB1为36M
//arr:自动重装值。
//psc:时钟预分频数
//这里使用的是定时器3!
void TIM3_Int_Init(u16 arr,u16 psc)
{RCC->APB1ENR|=1<<1;	//TIM3时钟使能    TIM3->ARR=arr;  	//设定计数器自动重装值//刚好1ms    TIM3->PSC=psc;  	//预分频器7200,得到10Khz的计数时钟		  TIM3->DIER|=1<<0;   //允许更新中断	  TIM3->CR1|=0x01;    //使能定时器3MY_NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2									 
}

5.2 定时器3中断服务程序

该部分程序在HARDWARE/timer.c/TIM3_IRQHandler(),主要作用是在定时器3中断溢出时进行LED1电平翻转,并清除SR寄存器中的中断标志位。具体代码如下所示:

//定时器3中断服务程序	 
void TIM3_IRQHandler(void)
{ 		    		  			    if(TIM3->SR&0X0001)//溢出中断{LED1=!LED1;			    				   				     	    	}				   TIM3->SR&=~(1<<0);//清除中断标志位 	    
}

5.3 轮询主函数

该部分程序在USER/test.c,主要作用是初始化定时器3(设置超时时间为500ms),在主循环函数中不断反转LED0电平,以示程序运行。具体代码如下所示:

#include "sys.h"
#include "delay.h"
#include "usart.h" 
#include "led.h" 
#include "timer.h" int main(void)
{					   Stm32_Clock_Init(9);	//系统时钟设置uart_init(72,115200); 	//串口初始化为115200delay_init(72);	   	 	//延时初始化 LED_Init();		  		//初始化与LED连接的硬件接口TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数5K次为500ms  while(1){LED0=!LED0;delay_ms(200);		   }	
}	 

六、上机测试

将程序烧录至STM32F103ZET6,可见LED1按照500ms进行翻转(定时器中断),LED0按照200ms闪烁(轮询主函数)。具体效果如下所示:

至此完成通用定时器3中断DEMO! 

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

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

相关文章

深度学习基础—残差网络ResNets

1.残差网络结构 当网络训练的很深很深的时候&#xff0c;效果是否会很好&#xff1f;在这篇论文中&#xff0c;作者给出了答案&#xff1a;Deep Residual Learning for Image Recognitionhttps://www.cv-foundation.org/openaccess/content_cvpr_2016/papers/He_Deep_Residual_…

EmEditor传奇脚本编辑器

主程序&#xff1a;EmEditor.exe 目前已有功能 可以自己指定一个快捷键 实现以下功能&#xff08;默认快捷键为&#xff1a;F1&#xff09; 以下全功能 都是鼠标所在行 按快捷键 &#xff08;默认快捷键&#xff1a;F1&#xff09; 1.在Merchant.txt中 一键打开NPC 没有…

Linux 外设驱动 应用 1 IO口输出

从这里开始外设驱动介绍&#xff0c;这里使用的IMX8的芯片作为驱动介绍 开发流程&#xff1a; 修改设备树&#xff0c;配置 GPIO1_IO07 为 GPIO 输出。使用 sysfs 接口或编写驱动程序控制 GPIO 引脚。编译并测试。 这里假设设备树&#xff0c;已经配置好了。不在论述这个问题…

Steam Deck掌机可装“黑苹果” 开发者成功安装macOS 15 Sequoia

在Steam Deck掌机上运行Windows 11相对轻松&#xff0c;但要让其成功搭载“黑苹果”系统则颇具挑战性。近日&#xff0c;有博主勇于尝试&#xff0c;将macOS 15 Sequoia安装到了Steam Deck上。 开发者kaitlyn在X平台上分享道&#xff1a;“在朋友们的鼎力相助下&#xff0c;我…

SQL专项练习第六天

Hive 在处理不同数据需求时的灵活性和强大功能&#xff0c;包括间隔连续问题的处理、行列转换、交易数据查询、用户登录统计以及专利数据分析等方面。本文将介绍五个 Hive 数据处理问题的解决方案&#xff0c;并通过实际案例进行演示。 先在home文件夹下建一个hivedata文件夹&a…

Unity Shader Graph基础包200+节点及术语解释

目录 Master Stack: Vertex block&#xff1a; Fragment block​编辑 Alpha Clip Threshold Dither transparency Graph Inspector Texture 2d Array/Texture 3d Virtual Texture Sampler State Keywords Boolean keyword 右键显示所有节点 简化测试系列节点&#x…

初入网络学习第一篇

引言 不磨磨唧唧&#xff0c;跟着学就好了&#xff0c;这个是我个人整理的学习内容梳理&#xff0c;学完百分百有收获。 1、使用的网络平台:eNSP 下载方法以及内容参考这篇文章 华为 eNSP 模拟器安装教程&#xff08;内含下载地址&#xff09;_ensp下载-CSDN博客https://b…

DBMS-3.4 SQL(4)——存储过程和函数触发器

本文章的素材与知识来自李国良老师和王珊老师。 存储过程和函数 一.存储过程 1.语法 2.示例 &#xff08;1&#xff09; 使用DELIMITER更换终止符后用于编写存储过程语句后&#xff0c;在下次执行SQL语句时记得再使用DELIMITER将终止符再换回分号。 使用DELIMITER更换终止符…

数据分布过于集中 怎么办,python 人工智能 ,数据分析,机器学习pytorch tensorflow ,

数据分布过于集中&#xff0c;意味着数据的大部分值都聚集在某个特定区间内&#xff0c;这可能会导致统计分析的结果不够稳健&#xff0c;或者模型训练时出现过拟合等问题。针对这种情况&#xff0c;可以考虑以下几种方法来处理&#xff1a; 变换成 1. **数据转换**&#xff1…

MySQL多表查询:列子查询

先看我的表数据 dept表 emp表 列子查询&#xff0c;也就是多列作为子查询去寻找一些问题 常用操作符&#xff1a;IN, NOT IN, ANY, SOME, ALL 1.查询 "销售部" 和 "市场部" 的所有员工的信息&#xff08;拆分成以下两个问题&#xff09; a. 查询"销…

基于STM32的数字温度传感器设计与实现

引言 STM32 是由意法半导体&#xff08;STMicroelectronics&#xff09;开发的基于 ARM Cortex-M 内核的微控制器系列&#xff0c;以其强大的处理能力、丰富的外设接口和低功耗著称&#xff0c;广泛应用于嵌入式系统设计中。在这篇文章中&#xff0c;我们将介绍如何基于 STM32…

如何用python抓取豆瓣电影TOP250

1.如何获取网站信息&#xff1f; &#xff08;1&#xff09;调用requests库、bs4库 #检查库是否下载好的方法&#xff1a;打开终端界面&#xff08;terminal&#xff09;输入pip install bs4, 如果返回的信息里有Successfully installed bs4 说明安装成功&#xff08;request…

OJ在线评测系统 微服务 OpenFeign调整后端下 nacos注册中心配置 不给前端调用的代码 全局引入负载均衡器

OpenFeign内部调用二 4.修改各业务服务的调用代码为feignClient 开启nacos注册 把Client变成bean 该服务仅内部调用&#xff0c;不是给前端的 将某个服务标记为“内部调用”的目的主要有以下几个方面&#xff1a; 安全性: 内部API通常不对外部用户公开&#xff0c;这样可以防止…

Linux操作系统——概念扫盲I

目录 虚拟机概念刨析 在那之前&#xff0c;询问什么是虚拟化&#xff1f; 现在来看看什么是虚拟机 虚拟机有啥好的 小差&#xff1a;那JVM也叫Java Virtual Machine&#xff0c;有啥区别呢&#xff1f; Reference 虚拟机概念刨析 我们下面来简单聊聊虚拟机这个概念。对于…

嵌入式硬件设计

嵌入式硬件设计是指针对嵌入式系统&#xff08;一种专用的计算机系统&#xff0c;通常嵌入到其他设备中&#xff09;进行的硬件设计工作。嵌入式系统广泛应用于消费电子、工业控制、医疗设备、汽车电子、航空航天等领域。以下是嵌入式硬件设计的主要内容和步骤&#xff1a; 1.…

浏览器前端向后端提供服务

WEB后端向浏览器前端提供服务是最常见的场景&#xff0c;前端向后端的接口发起GET或者POST请求&#xff0c;后端收到请求后执行服务器端任务进行处理&#xff0c;完成后向前端发送响应。 那浏览器前端向后端提供服务是什么鬼&#xff1f; 说来话长&#xff0c;长话短说。我在人…

微信步数C++

题目&#xff1a; 样例解释&#xff1a; 【样例 #1 解释】 从 (1,1) 出发将走 2 步&#xff0c;从 (1,2) 出发将走 4 步&#xff0c;从 (1,3) 出发将走 4 步。 从 (2,1) 出发将走 2 步&#xff0c;从 (2,2) 出发将走 3 步&#xff0c;从 (2,3) 出发将走 3 步。 从 (3,1) 出发将…

图论day55|深度优先搜索理论基础、98. 所有可达路径(卡码网)

图论day55|深度优先搜索理论基础、98. 所有可达路径(卡码网&#xff09; 思维导图汇总深度优先搜索理论基础98.所有可达路径(卡码网)1.邻接矩阵法2.邻接表法 思维导图汇总 深度优先搜索理论基础 深度优先搜索&#xff08;dfs&#xff09;与广度优先搜索&#xff08;bfs&#xf…

QSerialPort 串口通信示例

之前使用过MFC写过串口通信的示例&#xff0c;今年学了Qt&#xff0c;特意使用Qt写了串口通信的示例&#xff0c;发现比MFC要容易一些&#xff0c; MFC串口示例如下&#xff1a; Qt示例如下&#xff1a; Qt这个做的很简单&#xff0c;主要还是想验证一下api&#xff0c; 核心…

Python中对象obj类型确定最pythonic的方式——isinstance()函数

python中确定对象obj的类型&#xff0c;isinstance函数最是优雅&#xff0c;type、issubclass等函数也可以&#xff0c;但终究“曲折”。 (笔记模板由python脚本于2024年10月07日 19:42:38创建&#xff0c;本篇笔记适合喜欢python的coder翻阅) 【学习的细节是欢悦的历程】 Pyth…