STM32 TIM定时器配置

TIM简介

TIM(Timer)定时器

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

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

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

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

定时器类型

定时中断基本结构

计数器时序:

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

                                                              = CK_PSC (72M)/ (PSC + 1) / (ARR + 1)

预分频器时序:

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

定时器中断代码: 

TIM函数介绍:

        下面的函数对应着定时中断的结构

//时基单元初始化
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);

//使能中断输出信号
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);

//选择内部时钟
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

//选择ITRx其他定时器时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);

//选择TIx捕获通道的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

//选择ETR通过外部时钟模式1输入的时钟
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

//选择ETR通过外部时钟模式2输入的时钟
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

//单独配置ETR引脚的预分频器、极性、滤波器这些参数
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter);

参数更改函数:

//单独写预分频值
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);

配置定时器(内部时钟):

打开时钟

这次初始化TIM2,也就是通用定时器,TIM2是APB1的总线外设。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟

选择内部时钟

这里不写这行代码也行,因为定时器上电后默认就是使用内部时钟

 TIM_InternalClockConfig(TIM2);//选择内部时钟

配置时基单元

//-----------------------------配置时基单元---------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	
	 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;//重复计数器的值(这个是高级寄存器才有的,这里不需要用直接给0)
	 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure); //TIM初始化
	
	//-----------------------------配置时基单元---------------------------------

使能更新中断

 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路

NVIC配置

这里的中断通道选择TIM2的中断通道。

//-----------------------------NVIC配置-------------------------------------
	
	NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体变量
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
//-----------------------------NVIC配置-------------------------------------

启动定时器:

TIM_Cmd(TIM2,ENABLE);//启动定时器

整体函数:

void Timer_Init(void)
{
	 //---------------------------定义结构体变量-------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	 NVIC_InitTypeDef NVIC_InitStructure;//定义NVIC结构体变量
	
	//---------------------------定义结构体变量-------------------------------
	
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟
	
	 TIM_InternalClockConfig(TIM2);//选择内部时钟
	
	//-----------------------------配置时基单元---------------------------------
	
	 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;						 //重复计数器的值(这个是高级寄存器才有的,这里不需要用直接给0)
	 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);						 //TIM初始化
	
	//-----------------------------配置时基单元---------------------------------
	 
	 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路
	
	 
	//-----------------------------NVIC配置-------------------------------------
	
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
	//-----------------------------NVIC配置-------------------------------------
	
	 TIM_Cmd(TIM2,ENABLE);//启动定时器
}

中断函数:

实现定时器计时功能。

uint16_t Num = 0;
//中断函数

void TIM2_IRQHandler(void)
{
	//获取中断标志位,判断是否触发中断
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		Num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
		
		
	}
	
}

这里定义了一个变量Num,所以需要在头文件了extern一下,让其他工程文件也能用这个变量。

主函数:

完成了定时器计时功能,没过一秒,Num + 1.在屏幕上显示出来。

#include "timer.h"
int main(void)
{
	LED_Init();
	OLED_Init();
	Timer_Init();
	OLED_ShowString(1, 3, "Num:");
	while(1)
    {
	
	    OLED_ShowNum(1, 5, Num, 5);
	

    }	
	
	
}

这里上电以及复位不是从零开始,需要在NVIC配置之前清除一下标志位

配置外部时钟:

选择外部时钟模式

与内部时钟配置一样,只需要选择外部时钟模式以及加一个GPIO配置。

配置GPIO

//-----------------------------GPIO配置-------------------------------------
	
	 GPIO_InitTypeDef GPIO_InitStructure;				//定义GPIO结构体变量
	 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;		//选择上拉输入
	 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;    		//配置引脚
	 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//速率
	
	 GPIO_Init(GPIOA, &GPIO_InitStructure);//GPIO初始化
	
//-----------------------------GPIO配置-------------------------------------

整体函数配置:

void Timer_Init(void)
{
	 //---------------------------定义结构体变量-------------------------------
	
	 TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//定义TIM结构体变量
	 NVIC_InitTypeDef NVIC_InitStructure;							 //定义NVIC结构体变量
	 GPIO_InitTypeDef GPIO_InitStructure;							 //定义GPIO结构体变量
	//---------------------------定义结构体变量-------------------------------
	
	 RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//打开TIM2的外设时钟
	 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//打开GPIO A族时钟
	 TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted,0x0F);//选择外部时钟模式
	
	//-----------------------------GPIO配置-------------------------------------
	
	 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);//GPIO初始化
	
	//-----------------------------GPIO配置-------------------------------------
	
	//-----------------------------配置时基单元---------------------------------
	
	 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;						 //重复计数器的值(这个是高级寄存器才有的,这里不需要用直接给0)
	 TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);						 //TIM初始化
	
	//-----------------------------配置时基单元---------------------------------
	 
	 TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);						//开启更新中断到NVIC通路
	
	 TIM_ClearITPendingBit(TIM2,TIM_IT_Update);        		//清除标志位
	//-----------------------------NVIC配置-------------------------------------
	
	
	
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//选择中断分组2
	
	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);//NVIC初始化
	
	//-----------------------------NVIC配置-------------------------------------
	
	 TIM_Cmd(TIM2,ENABLE);//启动定时器
}

功能中断函数:

uint16_t Num = 0;
//中断函数

void TIM2_IRQHandler(void)
{
	//获取中断标志位,判断是否触发中断
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		
		Num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);//清除中断标志位
		
		
	}
	
}

uint16_t Timer_Getcount(void)
{
	return TIM_GetCounter(TIM2);
}

主函数:

#include "timer.h"
int main(void)
{
	LED_Init();
	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_Getcount(), 5);
    }		
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Spring Security(maven项目) 3.0.2.9版本 --- 改

前言: 通过实践而发现真理,又通过实践而证实真理和发展真理。从感性认识而能动地发展到理性认识,又从理性认识而能动地指导革命实践,改造主观世界和客观世界。实践、认识、再实践、再认识,这种形式,循环往…

数据结构(1)——算法时间复杂度与空间复杂度

目录 前言 一、算法 1.1算法是什么? 1.2算法的特性 1.有穷性 2.确定性 3.可行性 4.输入 5.输出 二、算法效率 2.1衡量算法效率 1、事后统计方法 2、事前分析估计方法 2.2算法的复杂度 2.3时间复杂度 2.3.1定义 2.3.2大O渐进表示法 2.3.3常见时间复…

巧妙利用数据结构优化部门查询

目录 一、出现的问题 部门树接口超时 二、问题分析 源代码分析 三、解决方案 具体实现思路 四、优化的效果 一、出现的问题 部门树接口超时 无论是在A项目还是在B项目中,都存在类似的页面,其实就是一个部门列表或者叫组织列表。 从页面的展示形式…

pycharm 中的 Mark Directory As 的作用是什么?

文章目录 Mark Directory As 的作用PYTHONPATH 是什么PYTHONPATH 作用注意事项 Mark Directory As 的作用 可以查看官网:https://www.jetbrains.com/help/pycharm/project-structure-dialog.html#-9p9rve_3 我们这里以 Mark Directory As Sources 为例进行介绍。 这…

机器学习10

自定义数据集 使用scikit-learn中svm的包实现svm分类 代码 import numpy as np import matplotlib.pyplot as pltclass1_points np.array([[1.9, 1.2],[1.5, 2.1],[1.9, 0.5],[1.5, 0.9],[0.9, 1.2],[1.1, 1.7],[1.4, 1.1]])class2_points np.array([[3.2, 3.2],[3.7, 2.9],…

二叉树——429,515,116

今天继续做关于二叉树层序遍历的相关题目,一共有三道题,思路都借鉴于最基础的二叉树的层序遍历。 LeetCode429.N叉树的层序遍历 这道题不再是二叉树了,变成了N叉树,也就是该树每一个节点的子节点数量不确定,可能为2&a…

WPF进阶 | WPF 样式与模板:打造个性化用户界面的利器

WPF进阶 | WPF 样式与模板:打造个性化用户界面的利器 一、前言二、WPF 样式基础2.1 什么是样式2.2 样式的定义2.3 样式的应用 三、WPF 模板基础3.1 什么是模板3.2 控件模板3.3 数据模板 四、样式与模板的高级应用4.1 样式继承4.2 模板绑定4.3 资源字典 五、实际应用…

六百六十六,盐豆不带盐了

我还有救吗...... P11040 #include <iostream> #include <vector> #include <cstring> using namespace std; const int MOD 998244353; const int MAXN 1e7 5; const int MAXM 1e7 5; int n, q; int m; int dpTable[MAXN][32]; int prefixSum[MAXN][32…

传输层协议 UDP 与 TCP

&#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 前置复盘&#x1f98b; 传输层&#x1f98b; 再谈端口号&#x1f98b; 端口号范围划分&#x1f98b; 认识知名端口号 (Well-Know Port Number) 二&#xf…

LabVIEW无人机航线控制系统

介绍了一种无人机航线控制系统&#xff0c;该系统利用LabVIEW软件与MPU6050九轴传感器相结合&#xff0c;实现无人机飞行高度、速度、俯仰角和滚动角的实时监控。系统通过虚拟仪器技术&#xff0c;有效实现了数据的采集、处理及回放&#xff0c;极大提高了无人机航线的控制精度…

最新功能发布!AllData数据中台核心菜单汇总

🔥🔥 AllData大数据产品是可定义数据中台,以数据平台为底座,以数据中台为桥梁,以机器学习平台为中层框架,以大模型应用为上游产品,提供全链路数字化解决方案。 ✨奥零数据科技官网:http://www.aolingdata.com ✨AllData开源项目:https://github.com/alldatacenter/…

【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理

llms-as-operating-systems-agent-memory llms-as-operating-systems-agent-memory内存 操作系统的内存管理

HarmonyOS:给您的应用添加通知

一、通知介绍 通知旨在让用户以合适的方式及时获得有用的新消息&#xff0c;帮助用户高效地处理任务。应用可以通过通知接口发送通知消息&#xff0c;用户可以通过通知栏查看通知内容&#xff0c;也可以点击通知来打开应用&#xff0c;通知主要有以下使用场景&#xff1a; 显示…

leetcode——二叉树的最近公共祖先(java)

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个节点也可以是它自己的…

【FreeRTOS 教程 六】二进制信号量与计数信号量

目录 一、FreeRTOS 二进制信号量&#xff1a; &#xff08;1&#xff09;二进制信号量作用&#xff1a; &#xff08;2&#xff09;二进制信号量与互斥锁的区别&#xff1a; &#xff08;3&#xff09;信号量阻塞时间&#xff1a; &#xff08;4&#xff09;信号量的获取与…

python学opencv|读取图像(五十五)使用cv2.medianBlur()函数实现图像像素中值滤波处理

【1】引言 在前述学习过程中&#xff0c;已经探索了取平均值的形式进行图像滤波处理。 均值滤波的具体的执行对象是一个nXn的像素核&#xff0c;对这个像素核内所有像素点的BGR值取平均值&#xff0c;然后把这个平均的BGR值直接赋给像素核中心位置的核心像素点&#xff0c;由…

OpenAI 正式推出Deep Research

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

多模态论文笔记——NaViT

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细解读多模态论文NaViT&#xff08;Native Resolution ViT&#xff09;&#xff0c;将来自不同图像的多个patches打包成一个单一序列——称为Patch n’ Pack—…

VLAN 基础 | 不同 VLAN 间通信实验

注&#xff1a;本文为 “ Vlan 间通信” 相关文章合辑。 英文引文&#xff0c;机翻未校。 图片清晰度限于原文图源状态。 未整理去重。 How to Establish Communications between VLANs? 如何在 VLAN 之间建立通信&#xff1f; Posted on November 20, 2015 by RouterSwi…

使用Pygame制作“吃豆人”游戏

本篇博客展示如何使用 Python Pygame 编写一个简易版的“吃豆人&#xff08;Pac-Man&#xff09;” 风格游戏。这里我们暂且命名为 Py-Man。玩家需要控制主角在一个网格地图里移动、吃掉散布在各处的豆子&#xff0c;并躲避在地图中巡逻的幽灵。此示例可帮助你理解网格地图、角…