03:TIM定时器

目录

一:TIM

1:介绍

2:定时器的分类

3:基本定时器

4:通用定时器

 5:高级定时器

6:定时器的基本结构

二:定时中断功能

A:定时器定时器中断

1:连接图

​编辑 

2:步骤

3:函数介绍

4:代码

三:外部时钟功能

A:定时器外部时钟

1:连接图

2:函数介绍 

3:外部时钟代码


一:TIM

1:介绍

        TIM(Timer)定时器

        定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断

        16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时 (计数器、预分频器、自动重装寄存器构成时基单元)

        不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能

         根据复杂度和应用场景分为了高级定时器、通用定时器、基本定时器三种类型

2:定时器的分类

 STM32F103C8T6定时器资源:TIM1、TIM2、TIM3、TIM4

3:基本定时器

1 :  预分频器+CNT计数器+自动重装载寄存器=时基单元

2 : 基本定时器只能选择内部时钟;他们都为16位的

预分频器 : 可以对72MHZ的计数时钟进行预分频处理; 对输入的基准频率提前进行一个分频的操作

eg : 预分频器写0,那就是不分频,或者说是1分频 ; 输出频率=输入频率=72MHz

预分频器写1,那就是2分频,输出频率(实际分频系数)=输入频率/2=36MHz

预分频器写2,那就是3分频,输出频率(实际分频系数)=输入频率/3= 24MHz

所以预分频器的值和实际的分频系数相差了1;  实际分频系数=预分频器的值+1

计数器 : 计数器可以对预分频后的计数时钟进行计数,预分频器每来一个上升沿计数器就+1

        所以计数器的值在计时过程中会不断地自增运行,直到达到目标值(自动重装载寄存器)然后产生中断,然后在重新开始计数

自动重装载寄存器(固定值) : 储存的是我们的计数目标,产生中断的目标值,(当计数器达到目标值就产生中断)

流程: 基准时钟------->预分频器------>计数器<--------->自动重装载计数器

计数器不断自增,会和自动重装载寄存器比较,当两个的值相同时,产生更新中断和更新事件;

cpu会响应更新中断

4:通用定时器

 5:高级定时器

6:定时器的基本结构

二:定时中断功能

A:定时器定时器中断

我们使用的是通用定时器TIM2在案列中(内部时钟)

1:连接图

 

2:步骤

1: 开启时钟 (RCC)

2: 选择时基单元的时钟 (TIM_InternalClockConfig--选择内部时钟)

3: 配置时基单元  (TIM_TimeBaseInit)

4 : 使能更新中断( TIM_ITConfig中断时钟控制)

5: NICV的配置   (见 02: STM32)

6: 启动定时器  (TIM_Cmd)

3:函数介绍

在stm32f10x tim.h文件中的函数-----时钟源选择函数   (选择时基单元的时钟)

void TIM_InternalClockConfig(TIM_TypeDef* TIMx);


void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);


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


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


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


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

TIM_InternalClockConfig : 选择内部时钟

TIM_ITRxExternalClockConfig : 选择TIR其他定时器的时钟

TIM_TIxExternalClockConfig : 选择TIx捕获通道的时钟

TIM_ETRClockMode1Config : 选择ETR通过外部时钟模式1输入的时钟

TIM_ETRClockMode2Config : 选择ETR通过外部时钟模式2输入的时钟

TIM_ETRConfig : 单独用来配置ETR引脚的预分频器、极性、滤波器这些参数的

 在stm32f10x tim.h文件中的函数-------时基单元函数

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

TIM_TimeBaseInit : 时基单元初始化,;TIMX选择某个定时器;  TIM_TimeBaseInitStruct:结构体包含了TIM配置的一些参数;

 在stm32f10x tim.h文件中的函数-------中断输出控制函数

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

TIM_ITConfig : 使能中断输出信号

 在stm32f10x tim.h文件中的函数-------运行控制函数函数

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

 TIM_Cmd : 选择启动那个定时器, 选择使能还有失能

 在stm32f10x tim.h文件中的函数-------单独修改初始化函数中的重要参数

不能为了某一个参数.直接重新初始化,太关于麻烦,直接更改某一个参数即可

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


void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);

void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);
 

void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);
 

uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);
 

TIM_PrescalerConfig :  单独写预分频值

TIM_CounterModeConfig : 改变计数器的计数模式

TIM_ARRPreloadConfig : 自动重装器预装功能配置

TIM_SetCounter : 给计数器写入一个值

TIM_SetAutoreload : 给自动重装器写入一个值

TIM_GetCounter : 获取当前计数器的值

TIM_GetPrescaler :获取当前的预分频器的值

在stm32f10x tim.h文件中的函数--其他函数

void TIM_DeInit(TIM_TypeDef* TIMx);

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

TIM_DeInit : 恢复缺省配置

TIM_TimeBaseStructInit : 结构体变量赋一个默认值

4:代码

#include "stm32f10x.h"                  // Device header
#include "OLED.h"
#include "Timer.h"
int16_t Num;extern int16_t Num;
void Timer_init(void){
//第一步是开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
//第二步,选择时基单元的时钟 (stm23上电默认使用的是内部时钟,这一行代码可以省略)
TIM_InternalClockConfig(TIM2);
//第三步,配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
/*计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1定时频率=72M/(PSC+1)/(ARR+1)72MHZ=72000KHZ72000KHZ/7200=10KHZ=10000HZT=1/F   T=1/10000hz=0.0001s=0.1ms然后以0.1ms的周期计10 000个数,所以就是1s*/
TIM_TimeBaseInitStructure.TIM_Period=10000-1;			//自动重装载寄存器ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=7200-1;  //预分频器PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器特有的(重复寄存器)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//第四使能更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_ClearFlag(TIM2, TIM_FLAG_Update);  //手动清除更新中断标志位//第五步NICV的配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
//第六步启动定时器
TIM_Cmd(TIM2,ENABLE);
}void TIM2_IRQHandler(){//检查中断标志位if (	TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//清除标志位Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}
}int main(void)
{OLED_Init();Timer_init();OLED_ShowString(1, 1, "Num:");while (1){OLED_ShowNum(1,5,Num,5);}
}

为什么要清除中断标志位

响应中断条件是:中断使能中断标志同时成立

单片机要靠查询中断标志来判断是否要进入中断,如果你不清除中断标志,本次中断退出,单片机又会检测到中断标志,因此重复进入中断

在STM32微控制器中,中断是一种重要的机制,用于响应外部事件或内部条件的变化。当一个中断事件发生时,相应的中断标志位会被置位(1),以表示中断事件已经发生。但是,在处理完中断之后,必须清除中断标志位(0),以确保下一次中断事件的正确触发。

清除中断标志位的主要目的有以下几个方面:

1. 防止重复触发:如果不清除中断标志位,当中断处理程序退出后,如果中断标志位仍然保持置位状态,可能会导致重复触发中断。这样会导致中断处理程序不停地执行,影响系统正常运行。

2. 确保正确的中断优先级:在STM32微控制器中,不同的外设和中断源具有不同的优先级。当多个中断源同时触发时,只有优先级最高的中断源会被处理。如果不清除中断标志位,可能会导致错误的中断源被处理,影响系统的功能和性能。

3. 确保正确的中断嵌套:STM32微控制器支持中断的嵌套执行。当一个高优先级的中断正在执行时,如果有一个更高优先级的中断进来,系统会自动挂起当前中断,转而执行更高优先级的中断。在挂起期间,中断标志位可能会保持置位状态。当更高优先级的中断执行完毕后,必须清除该中断的标志位,以便继续执行之前挂起的中断。

因此,为了确保中断系统的正确运行,必须在中断处理程序中清除相应的中断标志位。这可以通过写入相应的寄存器或调用相应的函数来实现。

时间的计算

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

首先72M进行7200分频,得到是10K的计数频率

在10K频率下,记10000个数,就是1s的时间

Arr是自动重装 psc预分频

方表明最大值是0-65535。-1表示有偏差

频率的单位是Hz; 周期的单位是s;

Hz<KHz<MHz; 都是千进的

s秒,ms毫秒,us微秒,ns纳秒;  都是千进的

72M进行7200分频,得到10KHz的计数频率。

T=1/F 所以T=1/10 000hz = 0.0001s = 0.1ms

然后以0.1ms的周期计10 000个数,所以就是1s
 

    72MHZ=72000KHZ
    72000KHZ/7200=10KHZ=10000HZ
    T=1/F   T=1/10000hz=0.0001s=0.1ms
    然后以0.1ms的周期计10 000个数,所以就是1s

三:外部时钟功能

A:定时器外部时钟

1:连接图

2:函数介绍 

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

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

TIM_GetCounter :   它用于获取定时器计数器的当前值

TIM_ETRClockMode2Config : 选择ETR通过外部时钟模式2输入的时钟


3:外部时钟代码


#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"
extern int16_t Num;
void Timer_init(void){
//第一步是开启时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef A;
A.GPIO_Mode=GPIO_Mode_IPU;  //上拉
A.GPIO_Pin=GPIO_Pin_0;
A.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOA,&A);
//第二步,选择时基单元的时钟 (stm23上电默认使用的是内部时钟,这一行代码可以省略)//TIM_ExtTRGPolarity_NonInverted 高电平或者上升沿有效
TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0f);//选择ETR通过外部时钟模式2输入的时钟//第三步,配置时基单元
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数
/*计数器溢出频率:CK_CNT_OV = CK_CNT / (ARR + 1)= CK_PSC / (PSC + 1) / (ARR + 1定时频率=72M/(PSC+1)/(ARR+1)72MHZ=72000KHZ72000KHZ/7200=10KHZ=10000HZT=1/F   T=1/10000hz=0.0001s=0.1ms然后以0.1ms的周期计10 000个数,所以就是1s*/
TIM_TimeBaseInitStructure.TIM_Period=10-1;			//自动重装载寄存器ARR
TIM_TimeBaseInitStructure.TIM_Prescaler=1-1;  //预分频器PSC
TIM_TimeBaseInitStructure.TIM_RepetitionCounter=0;//高级定时器特有的(重复寄存器)
TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);//第四使能更新中断TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);TIM_ClearFlag(TIM2, TIM_FLAG_Update);//手动清除更新中断标志位//第五步NICV的配置
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);	NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel=TIM2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_Init(&NVIC_InitStructure);
//第六步启动定时器
TIM_Cmd(TIM2,ENABLE);
}void TIM2_IRQHandler(){//检查中断标志位if (	TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){//清除标志位Num++;TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}}uint16_t  Timer_GetCounter(void){//TIM_GetCounter。它用于获取定时器计数器的当前值。return TIM_GetCounter(TIM2);  
}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);}
}

本实验实验了外部时钟(对外式红外传感计数器),当对外式红外传感计数器达到了某个数值是触发定时器

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

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

相关文章

Git 安装、配置并把项目托管到码云 Gitee

错误聚集篇&#xff1a; 由于我 git 碰见大量错误&#xff0c;所以集合了一下&#xff1a; git 把项目托管到 码云出现的错误集合_打不着的大喇叭的博客-CSDN博客https://blog.csdn.net/weixin_49931650/article/details/132460492 1、安装 git 1.1 安装步骤 1.1.1 下载对应…

《Go 语言第一课》课程学习笔记(十一)

控制结构 if 的“快乐路径”原则 针对程序的分支结构&#xff0c;Go 提供了 if 和 switch-case 两种语句形式&#xff1b;而针对循环结构&#xff0c;Go 只保留了 for 这一种循环语句形式。 if 语句 if 语句是 Go 语言中提供的一种分支控制结构&#xff0c;它也是 Go 中最常…

在云服务器上安装Jenkins

说明&#xff1a;Jenkins是一个部署项目的平台&#xff0c;通过Jenkins可以省去从项目开发–>部署项目之间的所有流程&#xff0c;做到代码提交即上线。本文介绍在云服务CentOS上安装Jenkins。 前提 安装Jenkins之前&#xff0c;先要在云服务上安装JDK、Maven、Git&#x…

iOS开发之查看静态库(.a/.framework)中包含的.o文件和函数符号(ar,nm命令)

.a/.framework其实是把编译生成的.o文件&#xff0c;打包成一个.a/.framework文件。a的意思是archive/归档的意思。 查看静态库.a文件包含的内容用下面的命令解压&#xff1a; ar x xxx.a 用ar命令打包静态库&#xff1a; 参数r是将后面的*.o或者*.a文件添加到目标文件中 参数…

开源在企业中的角色和价值

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

iOS 17 及 Xcode 15.0 Beta7 问题记录

1、iOS 17 真机调试问题 iOS 17之后&#xff0c;真机调试Beta版本必须使用Beta版本的Xcode来调试&#xff0c;用以前复制DeviceSupport 方式无法调试&#xff0c;新的Beta版本Xcode中&#xff0c;已经不包含 iOS 17目录。如下图&#xff1a; 解决方案&#xff1a; 1&#x…

Matlab绘制灰度直方图

直方图是根据灰图像绘制的&#xff0c;而不是彩色图像通。查看图像直方图时候&#xff0c;需要先确定图片是否为灰度图&#xff0c;使用MATLAB2019查看图片是否是灰度图片&#xff0c;在读取图片后在MATLAB界面的工作区会显示读取的图像矩阵&#xff0c;如果是&#xff0c;那么…

数据结构基础:P3-树(上)----编程作业02:List Leaves

本系列文章为浙江大学陈越、何钦铭数据结构学习笔记&#xff0c;系列文章链接如下&#xff1a; 数据结构(陈越、何钦铭)学习笔记 文章目录 一、题目描述二、整体思路与实现代码 一、题目描述 题目描述&#xff1a; 给定一棵树&#xff0c;按照从上到下、从左到右的顺序列出所有…

node.js 简单使用 开始

1.概要 问&#xff1a;体验一下node.js 看一下如何运行。 答&#xff1a;使用命令 node 文件名.js 2.举例 2.1 代码准备(main.js) console.log(第一行node.js代码); 2.2 运行效果

计算机终端核心安全配置规范

声明 本文是学习 政务计算机终端核心配置规范. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 范围 本标准提出了政务计算机终端核心配置的基本概念和要求&#xff0c;规定了核心配置的自动化实现方法&#xff0c;规范了核心配置实施流程。 本标准适…

word文档怎么压缩大小?文件压缩方法分享

Word文档是工作和学习中常用的格式&#xff0c;有时候在编辑外后发现文档体积太大了&#xff0c;想要分享或者上传到平台都不行&#xff0c;今天就给大家总结了几个Word文档压缩方法&#xff0c;轻松帮助大家解决Word文档过大的问题&#xff01; 一、压缩Word中的图片 通常情况…

【C#学习笔记】委托和事件

文章目录 委托委托的定义委托实例化委托的调用多播委托 为什么使用委托&#xff1f;官方委托泛型方法和泛型委托 事件为什么要有事件&#xff1f;事件和委托的区别&#xff1a; 题外话——委托与观察者模式 委托 在 .NET 中委托提供后期绑定机制。 后期绑定意味着调用方在你所…