STM32-TIM定时器中断

news2024/11/18 14:53:47

目录

一、TIM(Timer)定时器简介

二、定时器类型

2.1基本定时器结构

2.2通用定时器结构

2.3高级定时器结构

三、定时中断基本结构

四、时序图分析

4.1 预分频器时序

4.2 计数器时序

4.3 计数器无预装时序(无影子寄存器)

4.4 计数器有预装时序(有影子寄存器)

五、RCC时钟树 

六、开发步骤

七、定时器函数

八、实验

8.1定时器定时中断

8.2定时器外部时钟


一、TIM(Timer)定时器简介

①定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断
②16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时

计数器:执行计数定时的一个寄存器,每来一个时钟,计数器加1

预分频器:对计数器的时钟进行分频,让这个计数更加灵活

自动重装寄存器:计数的目标值,计多少个时钟来申请一次中断
③不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能
④根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

二、定时器类型

2.1基本定时器结构

主模式触发DAC功能:把定时器的更新事件映射到触发输出TRGO(Trigger Out)的位置,TRGO直接接到DAC的触发转换引脚上,这样就不需要通过中断来触发DAC转换了。实现了硬件的自动化。  

 通用定时器和高级定时器除了向上计数模式,还有向下计数模式和中央对齐模式

2.2通用定时器结构

2.3高级定时器结构

三、定时中断基本结构

四、时序图分析

4.1 预分频器时序

计数器计数频率:CK_CNT = CK_PSC / (PSC + 1)

4.2 计数器时序

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

计数器时间:(PSC + 1)(ARR + 1)/CK_PSC

4.3 计数器无预装时序(无影子寄存器)

4.4 计数器有预装时序(有影子寄存器)

五、RCC时钟树 

作用:产生和配置时钟,将配置好的时钟发送到各个外设系统

开发技巧:

在SystemInit函数中,首先启动内部8MHz时钟为系统时钟运行,然后再启动外部时钟,进入PLL锁相环进行倍频,8MHz倍频9倍,得到72MHz,锁相环输出稳定之后,选择锁相环输出为系统时钟,这样就把系统时钟由8MHz变成了72MHz。

实际问题:

如果外部晶振出现问题,程序时钟慢了大概10倍,定时器定时1s,结果过了大概10s才进中断。是因为现在是以内部时钟8MHz运行的

六、开发步骤

①RCC打开时钟

②选择时基单元的时钟源

③结构体配置时基单元(预分频器,自动重装器,计数模式)

④配置输出中断控制,允许更新中断输出到NVIC

⑤配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级

⑥运行控制,使能计数器

⑦写定时器中断函数

七、定时器函数

=====================================================================

=================================基本函数=============================

void TIM_DeInit(TIM_TypeDef* TIMx);

//定时器恢复缺省配置


void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//时基单元初始化

//第一个参数:某个定时器,第二个参数:结构体

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

//把结构体变量赋默认值

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

//使能计数器

//第一个参数:TIMx选择定时器,第二个参数:使能或失能

void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

//使能中断输出信号(中断输出控制)

//第一个参数:TIMx选择定时器,第二个参数:哪个中断输出,第三个参数:使能或失能

=====================================================================

=========================配置时钟输入的函数=============================

void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

//选择内部时钟


void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//选择ITRx其他定时器时钟

//第一个参数:选择配置哪个定时器,第二个参数:选择要接入哪个定时器


void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,uint16_t TIM_ICPolarity, uint16_t ICFilter);

//选择TIx捕获通道的时钟

//第一个参数:TIMx,第二个参数:TIMx具体哪个引脚,第三、四个参数:输入极性和滤波器


void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);

//ETR通过外部时钟模式1输入时钟

//第一个参数:TIMx,第二个参数:外部触发预分频器,第三、四个参数:输入极性和滤波器


void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

//ETR通过外部时钟模式2输入时钟

//第一个参数:TIMx,第二个参数:外部触发预分频器,第三、四个参数:输入极性和滤波器


void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);

//单独配置ETR引脚的预分频器、极性、滤波器

//第一个参数:TIMx,第二个参数:外部触发预分频器,第三、四个参数:输入极性和滤波器

=====================================================================

===================更改关键参数函数(预分频值,自动重装载值)==============

void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);

//修改预分频值

//第一个参数:TIMx,第二个参数:预分频值,第三个参数:写入模式


void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

//修改计数器的计数模式

//第一个参数:TIMx,第二个参数:新的计数器模式


void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//自动重装器预装功能配置

//第一个参数:TIMx,第二个参数:预装功能使能或失能

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

//给计数器值

//第一个参数:TIMx,第二个参数:计数器值


void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

//给自动重装器写入值

//第一个参数:TIMx,第二个参数:自动重装值

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

//获取计数器值


uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

//获取预分频值

=====================================================================

============================获取和清除标志位函数========================

//主函数

FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

//中断函数

ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

八、实验

8.1定时器定时中断

实验现象:1s计数加一

代码实现

Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	/*一、RCC开启时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	/*二、选择时基单元的时钟源*/
	TIM_InternalClockConfig(TIM2);//选择内部时钟
	
	/*三、配置时基单元(预分频器,自动重装器,计数模式)*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;//采样频率(内部时钟+时钟分频)//不分频
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;//计数器模式
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;//ARR自动重装器值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;//PSC预分频器值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值(高级定时器才有)
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*避免刚初始化就进入中断(复位就是1,而不是0)*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	/*四、配置输出中断控制,允许更新中断输出到NVIC*/
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//开启更新中断到NVIC的通路
	
	/*五、配置NVIC,在NVIC打开定时器中断的通道,分配优先级*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	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);
	
	/*六、运行控制,使能计数器*/
	TIM_Cmd(TIM2,ENABLE);
}

/*中断函数模板
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}
*/

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main(void)
{
	OLED_Init();
	Timer_Init();
	
	OLED_ShowString(1,1,"Num:");
	OLED_ShowString(2,1,"CNT:");

	while (1)
	{
		OLED_ShowNum(1,5,Num,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5);//观察CNT计数器值的变化情况
	}
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num ++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

8.2定时器外部时钟

方法:定时器指定的外部引脚输入一个方波信号,来提供定时器计数的时钟 

实验现象:利用对射式红外传感器来手动模拟一个外部时钟,用挡光片,依次遮挡、移开来模拟一个方波,定时器计数值(CNT)逐次加一,当CNT到9后,产生一次中断,Num加一,CNT清零重新计数

代码实现

Timer.c

#include "stm32f10x.h"                  // Device header

void Timer_Init(void)
{
	/*一、RCC开启时钟 + GPIOA的初始化*/
	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);
	
	/*二、选择时基单元的时钟源*/
	TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x00);
	//通过ETR的外部时钟模式2,不分频,不反向(高电平/上升沿有效),外部触发滤波器
	
	/*三、配置时基单元(预分频器,自动重装器,计数模式)*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;//ARR自动重装器值
	TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;//PSC预分频器值
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;//重复计数器值
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*避免刚初始化就进入中断(复位就是1,而不是0)*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	
	/*四、配置输出中断控制,允许更新中断输出到NVIC*/
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	/*五、配置NVIC,在NVIC打开定时器中断的通道,分配优先级*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	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);
	
	/*六、运行控制,使能计数器*/
	TIM_Cmd(TIM2,ENABLE);
}

/*查看CNT的值*/
uint16_t Timer_GetCounter(void)
{
	return TIM_GetCounter(TIM2);
}

/*中断函数模板
void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}
*/

Timer.h

#ifndef __TIMER_H
#define __TIMER_H

void Timer_Init(void);
uint16_t Timer_GetCounter(void);

#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t Num;

int main(void)
{
	OLED_Init();
	Timer_Init();
	
	OLED_ShowString(1,1,"Num:");
	OLED_ShowString(2,1,"CNT:");

	while (1)
	{
		OLED_ShowNum(1,5,Num,5);
		OLED_ShowNum(2,5,Timer_GetCounter(),5);//观察CNT计数器值的变化情况
	}
}

void TIM2_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		Num ++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

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

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

相关文章

LVGL_V8.3入门二---实时时钟(模仿华为watch-UI)

系列文章目录 文章目录 系列文章目录前言一、实现效果二、代码解析 前言 在这个博客中,我们将深入探讨LVGL(Light and Versatile Graphics Library)版本8.3的实时时钟应用,以模仿华为 Watch UI 为例。LVGL是一款专为嵌入式系统和…

Jenkins简单介绍

学习目标 知道jenkins应用场景能够安装部署jenkins服务器能够实现gitgithubjenkins手动构建能够实现gitgitlabjenkins自动发布系统 认识jenkins Jenkins是一个可扩展的持续集成引擎,是一个开源软件项目,旨在提供一个开放易用的软件平台,使软…

Kafka集成springboot

安装kafka,直接到官网下载bin文件,本文使用windows进行使用kafka。 下载之后,第一步,启动zookeeper: zookeeper-server-start.bat ..\..\config\zookeeper.properties 第二步,启动kafka: kafka…

oops-framework框架 之 多语言设置文本、精灵和骨骼动画

引擎: CocosCreator 3.8.0 环境: Mac Gitee: oops-plugin-excel-to-json 注: 作者dgflash的oops-framework框架QQ群: 628575875 简介 作者dgflash在oops-framework的框架中提供了多语言,主要用于对文本、图片、骨骼动…

Verilog基础:寄存器输出的两种风格

相关文章 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 Verilog中的寄存器操作一般指的是那些对时钟沿敏感而且使用非阻塞赋值的操作。例如状态机中的状态转移,实际上就是一种寄存器操作,因为这相…

【docker 】centOS 安装docker

官网 docker官网 github源码 卸载旧版本 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine 安装软件包 yum install -y yum-utils \device-mapper-persistent-data…

自下而上-存储全栈(TiDB/RockDB/SPDK/fuse/ceph/NVMe/ext4)存储技术专家成长路线

数字化时代的到来带来了大规模数据的产生,各行各业都面临着数据爆炸的挑战。 随着云计算、物联网、人工智能等新兴技术的发展,对存储技术的需求也越来越多样化。不同应用场景对存储的容量、性能、可靠性和成本等方面都有不同的要求。具备存储技术知识和技…

基于 Gin 的 HTTP 中间人代理 Demo

前面实现的代理对于 HTTPS 流量是进行盲转的,也就是说直接在 TCP 连接上传输 TLS 流量,但是我们无法查看或者修改它的内容。当然了,通常来说这也是不必要的。不过对于某些场景下还是有必要的,例如使用 Fiddler 进行抓包或者监控其…

Flink 本地单机/Standalone集群/YARN模式集群搭建

准备工作 本文简述Flink在Linux中安装步骤,和示例程序的运行。需要安装JDK1.8及以上版本。 下载地址:下载Flink的二进制包 点进去后,选择如下链接: 解压flink-1.10.1-bin-scala_2.12.tgz,我这里解压到soft目录 [ro…

redis之缓存穿透,击透,雪崩~

以下为一个我们正常的缓存流程: 缓存雪崩: 在双十一的时候,淘宝的首页访问量是非常大的,所以它的很多数据是放在redis缓存里面,对应redis中的key,假设设置了缓存失效的时间为3小时,超过这三个小…

视觉学习笔记12——百度飞浆框架的PaddleOCR 安装、标注、训练以及测试

系列文章目录 虚拟环境部署 参考博客1 参考博客2 参考博客3 参考博客4 文章目录 系列文章目录一、简单介绍1.OCR介绍2.PaddleOCR介绍 二、安装1.anaconda基础环境1)anaconda的基本操作2)搭建飞浆的基础环境 2.安装paddlepaddle-gpu版本1)安装…

区块链实验室(29) - 关闭或删除FISCO日志

1. FISCO日志 缺省情况下,FISCO启动日志模块,日志记录的位置在节点目录中。以FISCO自带案例为例,4节点的FISCO网络,24个区块产生的日志大小,见下图所示。 2.关闭日志模块 当节点数量增大,区块高度增大时&…

利用Wix打包安装包

利用Wix打包安装包 背景具体步骤1、安装 WiX Toolset 工具集2、安装 WiX Toolset 系列 Visual Studio 插件3、创建Wix工程4、添加工程文件5、修改Product元素6、修改Package元素7、修改MajorUpgrade元素8、修改Media属性9、设置安装引导界面10、添加WPF项目文件11、添加桌面快捷…

资源三号卫星数字表面模型库

资源三号卫星数字表面模型库(简称ChinaDSM-China Digital Surface Model)是以资源三号卫星立体影像为数据源,采用自主知识产权的基于多基线、多匹配特征的地形信息自动提取技术,快速处理和生产提取的高精度、高保真15米格网数字表…

排序算法之四:直接选择排序

1.基本思想 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。 2.直接选择排序 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素 若它不是这组元素中的…

第 119 场 LeetCode 双周赛题解

A 找到两个数组中的公共元素 模拟 class Solution { public:vector<int> findIntersectionValues(vector<int> &nums1, vector<int> &nums2) {unordered_set<int> s1(nums1.begin(), nums1.end()), s2(nums2.begin(), nums2.end());vector<…

keepalived+lvs 对nginx做负载均衡和高可用

LVS_Director KeepAlivedKeepAlived在该项目中的功能&#xff1a; 1. 管理IPVS的路由表&#xff08;包括对RealServer做健康检查&#xff09; 2. 实现调度器的HA http://www.keepalived.orgKeepalived所执行的外部脚本命令建议使用绝对路径实施步骤&#xff1a; 1. 主/备调度器…

《深入浅出进阶篇》洛谷P3197 越狱——集合

洛谷P3197 越狱 题目大意&#xff1a; 监狱有 n 个房间&#xff0c;每个房间关押一个犯人&#xff0c;有 m 种宗教&#xff0c;每个犯人会信仰其中一种。如果相邻房间的犯人的宗教相同&#xff0c;就可能发生越狱&#xff0c;求有多少种状态可能发生越狱。 答案对100,003 取模。…

Python 网络爬虫(三):XPath 基础知识

《Python入门核心技术》专栏总目录・点这里 文章目录 1. XPath简介2. XPath语法2.1 选择节点2.2 路径分隔符2.3 谓语2.4 节点关系2.5 运算符3. 节点3.1 元素节点(Element Node)3.2 属性节点(Attribute Node)

MongoDB——基本概念+docker部署+基本命令

1.MongoDB相关概念 业务应用场景 MongoDB简介 BSON二进制的JSON 数据类型 MongDB的特点 2.单机部署 windows上的安装启动 windows版本的直接去官网下载即可&#xff0c;这里的安装运行我试了一次没有成功。干脆不用了&#xff0c;反正以后也不会在windows系统上用的这个 li…