STM32-TIM定时器中断

目录

一、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 headervoid 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_Hvoid 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 headervoid 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_Hvoid 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.mzph.cn/news/210687.shtml

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

相关文章

PyQt6 水平布局Horizontal Layout (QHBoxLayout)

锋哥原创的PyQt6视频教程: 2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 PyQt6 Python桌面开发 视频教程(无废话版) 玩命更新中~共计41条视频,包括:2024版 PyQt6 Python桌面开发 视频教程(无废话版…

[足式机器人]Part2 Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System

本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记-自动控制原理Ch1-1开环系统与闭环系统Open/Closed Loop System EG1: 烧水与控温水壶EG2: 蓄水与最终水位闭环控制系统 EG1: 烧水与控温水壶 EG2: 蓄水与最终水位 h ˙ q i n A − g h A R \dot{…

阿里云SLS采集jvm日志

一、背景 java应用部署在阿里云的k8s容器里,采集其日志的需求则是一个不可缺少的。而不同公司的jvm日志会存在很大的差异,所以本文仅以我的实际情况作一个示例,仅供有需要采集jvm日志的同学们一个参考。 我们打印的Jvm日志格式见下&#xf…

【干货分享】KingIOServer与三菱PLC的通讯的应用案例

哈喽,大家好,我是雷工! 最近一个项目涉及用KingIOServer采集三菱PLC数据,特记录通讯过程方便备忘。 一、版本说明: 1、KingIOServer版本:3.7SP2 2、PLC型号:Q03UDV 和Q03UDE自带以太网网口。…

【Dubbo3云原生微服务开发实战】「Dubbo前奏导学」 RPC服务的底层原理和实现

RPC服务 RPC服务介绍RPC通信模式RPC架构组成RPC技术要点RPC通信技术选项分析RPC实战开发6大基础组件基础组件之Guava基础组件之Hutools基础组件之ReflectionASM基础组件之FastJSON/FastJSON2基础组件之FST相比FastJSON的优势 基础组件之Commons-Codec RPC框架层面选项分析RPC组…

持续集成交付CICD:Jenkins配置Nexus制品上传流水线

目录 一、实验 1.Jenkins配置制品上传流水线 二、问题 1.上传制品显示名称有误 一、实验 1.Jenkins配置制品上传流水线 (1) 新建流水线项目 (2)描述 (3)添加参数 (4)查看构建首页 (5&…

实现简易的一对一用户聊天

服务端 package 一对一用户;import java.awt.BorderLayout; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.Vector…

Redis课程:黑马点评

文章目录 基于Redis实现短信登录商户查询缓存优惠券秒杀一人一单 分布式锁Redis分布式锁误删情况说明解决Redis分布式锁误删问题使用lua脚本解决分布式锁的原子性问题 基于阻塞队列实现秒杀优化Redis消息队列优化秒杀业务达人探店参考 本文是根据黑马程序员的视频课程 黑马程序…

Kubernetes架构及核心部件

文章目录 1、Kubernetes集群概述1.1、概述1.2、通过声明式API即可 2、Kubernetes 集群架构2.1、Master 组件2.1.1、API Server2.1.2、集群状态存储2.1.3、控制器管理器2.1.4、调度器 2.2、Worker Node 组件2.2.1、kubelet2.2.2、容器运行时环境2.2.3、kube-proxy 2.3、图解架构…

深入解析Node.js:V8引擎、事件驱动和非阻塞式I/O

文章目录 1. 引言2. 什么是Node.js?3. V8引擎3.1 V8引擎简介3.2 V8引擎的特点 4. 事件驱动4.1 事件循环4.2 事件触发与监听4.2.1 代码示例 4.3 异步回调4.3.1 代码示例 5. 非阻塞式I/O5.1 非阻塞式I/O的优势5.2 异步与同步的对比5.2.1 同步I/O的代码示例5.2.2 异步I…

Linux 系统上配置 SSH 密钥

1. 生成 SSH 密钥 打开终端,运行以下命令来生成 SSH 密钥: ssh-keygen -t rsa -b 4096 -C "wqzbxhexample.com" 替换 "wqzbxhexample.com" 为你在 GitHub 注册时使用的邮箱地址。 2. 添加 SSH 密钥到 SSH 代理 运行以下命令来启…

ROS gazebo 机器人仿真,环境与robot建模,添加相机 lidar,控制robot运动

b站上有一个非常好的ros教程234仿真之URDF_link标签简介-机器人系统仿真_哔哩哔哩_bilibili,推荐去看原视频。 视频教程的相关文档见:6.7.1 机器人运动控制以及里程计信息显示 Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程 本文对视频教程…

【论文精读】REACT: SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS

REACT: SYNERGIZING REASONING AND ACTING IN LANGUAGE MODELS 前言ABSTRACT1 INTRODUCTION2 REACT: SYNERGIZING REASONING ACTING3 KNOWLEDGE-INTENSIVE REASONING TASKS3.1 SETUP3.2 METHODS3.3 RESULTS AND OBSERVATIONS 4 DECISION MAKING TASKS5 RELATED WORK6 CONCLUSI…

phpstudy搭建WordPress教程

一、phpstudy新建配置WordPress 打开phpstudy,启动Apache(或者Nginx)和MySQL服务 来到数据库部分,点击[创建数据库],填写新建数据库的名称,用户名以及密码,完成后点击确认 来到网站部分&#x…

Course2-Week4-决策树

Course2-Week4-决策树 文章目录 Course2-Week4-决策树1. 决策树的直观理解2. 构建单个决策树2.1 熵和信息增益2.2 构建决策树——二元输入特征2.3 构建决策树——多元输入特征2.4 构建决策树——连续的输入特征2.5 构建回归树——连续的输出结果(选修)2.6 代码实现-递归构建单个…

解决 php 连接mysql数据库时报错:Fatal error: Class ‘mysqli’ not found in问题

在使用php对mysql进行连接的过程中,出现了Fatal error: Uncaught Error: Class "mysqli" not found in的问题 解决方案 这个错误通常表示您的PHP代码中缺少MySQL扩展或者没有启用MySQL扩展。 我们首先确认一下PHP环境中已经安装了MySQL扩展。检查一下自己…

Redis如何做内存优化?

Redis如何做内存优化? 1、缩短键值的长度 缩短值的长度才是关键,如果值是一个大的业务对象,可以将对象序列化成二进制数组; 首先应该在业务上进行精简,去掉不必要的属性,避免存储一些没用的数据&#xff1…

【淘宝网消费类电子产品销售数据可视化】

淘宝网消费类电子产品销售数据可视化 引言数据爬取与处理数据可视化系统功能1. 总数据量分析2. 店铺总数据3. 店铺销售额排名4. 不同电子商品销售价格5. 单个商品价格排名6. 不同省份平均销量7. 不同地区的平均销售额8. 省份数量9. 每个省份有用的平均个数 创新点结语 引言 随…

Linux 中 find 查找

目录 1.普通查询 2.按照文件大小查找 3.忽略文件字母大小写查询 4.根据修改时间查找 5. 取反 ! 6.根据用户查询 7.对查找出来的内容进行操作 1.普通查询 find 路径 -name "文件名" 如查看 etc 目录下的passwd 的文件 find /etc -name "passwd&quo…

kettle完成mysql表与表之间的更新和插入

版本:20231209 kettle完成数据库表与表之间的转换非常的简单,只需要在输入模块选择:输入表;在输出模块选择:插入和更新表模块 实例展示:将表stu1的数据同步到stu2,并覆盖掉stu2原本的数据。 cr…