STM32之TIMx(定时器)理解及运用

news/2024/5/18 22:16:43 标签: stm32, time, 硬件, 程序设计

文章目录

  • 一、定时器的分类
  • 二、定时器基本定时功能
    • 1、定时时间换算
    • 2、定时器定时程序设计
    • 3、定时器周期中断设计
  • 三、高级定时器
    • 1、定时器的输出比较功能
      • 1、PWM输出模式
      • 2、四路PWM输出控制电机程序
    • 2、定时器的输入捕获功能


一、定时器的分类

1、基本定时器:只能定时。
2、通用定时器:定时、输出比较、输入捕获、四个外部IO。
3、高级定时器:定时、输出比较、输入捕获、八个外部IO,三相电机互补输出信号。

4、高级控制定时器和通用定时器在基本定时器的基础上引入了外部引脚,可以实现输入捕获和输出比较功能。

5、高级控制定时器比通用定时器增加了可编程死区互补输出、重复计数器、带刹车(断路)功能,这些功能都是针对工业电机控制方面。

在这里插入图片描述


二、定时器基本定时功能

1、定时时间换算

记住这个图很重要!!

对于时间的换算,对于定时器外设。
1、首先是时钟源的频率,经过APB1的预分频,定时器时TIMxCLK=36*2=72M。
2、PSC预分频器,,PSC取值1~65536,对TIMxCLK分频
3、分频后到CNT计数器,其值为CK_CNT=TIMxCLK/(PSC+1),最大值为65535
4、CK_CNT的最大值存放在ARR寄存器中,计数超出最大值会触发溢出中断,在已经使能中断的情况下。

以上四步,最后要得到的就是CK_CNT=TIMxCLK/(PSC+1),可以理解为频率。

5、定时器定时时间=中断周期*中断次数(n)。

         定时器记一个数的时间,T=1/CK_CNT=(PSC+1)/TIMxCLK
        一共记多少数由ARR决定。
        所以,中断周期= T * ARR= ARR/CK_CNT。

定时器定时时间=(n*ARR)/CK_CNT。

2、定时器定时程序设计

编程步骤:
1、开启定时器时钟
2、初始化时基初始化结构体
3、使能更新中断,配置NVIC
4、编写定时器中断服务函数
代码如下:

1)timer,h


/********************基本定时器TIM参数定义,只限TIM6、7************/
#define BASIC_TIM6 // 如果使用TIM7,注释掉这个宏即可

#ifdef  BASIC_TIM6 // 使用基本定时器TIM6
#define            BASIC_TIM                   TIM6
#define            BASIC_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            BASIC_TIM_CLK               RCC_APB1Periph_TIM6
#define            BASIC_TIM_Period            (1000-1)
#define            BASIC_TIM_Prescaler         71
#define            BASIC_TIM_IRQ               TIM6_IRQn
#define            BASIC_TIM_IRQHandler        TIM6_IRQHandler

#else  // 使用基本定时器TIM7
#define            BASIC_TIM                   TIM7
#define            BASIC_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            BASIC_TIM_CLK               RCC_APB1Periph_TIM7
#define            BASIC_TIM_Period            1000-1
#define            BASIC_TIM_Prescaler         71
#define            BASIC_TIM_IRQ               TIM7_IRQn
#define            BASIC_TIM_IRQHandler        TIM7_IRQHandler

#endif
/**************************函数声明********************************/

void BASIC_TIM_Init(void);

2)timer.c

// 基本定时器TIMx,x[6,7]定时初始化函数

#include "timer.h" 

// 中断优先级配置
static void BASIC_TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    // 设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
		// 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;	
		// 设置主优先级为 0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
	  // 设置抢占优先级为3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

/*
 * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
 * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
 * 另外三个成员是通用定时器和高级定时器才有.
 *-----------------------------------------------------------------------------
 *typedef struct
 *{ TIM_Prescaler            都有
 *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
 *  TIM_Period               都有
 *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
 *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
 *}TIM_TimeBaseInitTypeDef; 
 *-----------------------------------------------------------------------------
 */


static void BASIC_TIM_Mode_Config(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
		
		// 开启定时器时钟,即内部时钟CK_INT=72M
    BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
	
		// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;	

	  // 时钟预分频数为
    TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;
	
		// 时钟分频因子 ,基本定时器没有,不用管
    //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
		
		// 计数器计数模式,基本定时器只能向上计数,没有计数模式的设置
    //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 
		
		// 重复计数器的值,基本定时器没有,不用管
		//TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
	
	  // 初始化定时器
    TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
		
		// 清除计数器中断标志位
    TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
	  
		// 开启计数器中断
    TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
		
		// 使能计数器
    TIM_Cmd(BASIC_TIM, ENABLE);	
}

void BASIC_TIM_Init(void)
{
	BASIC_TIM_NVIC_Config();
	BASIC_TIM_Mode_Config();
}
//中断服务函数
void  BASIC_TIM_IRQHandler (void)
{
	if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) 
	{	
		time++;
		//全局变量,记录中断次数,当time达到一定值,就可换算为定时时间
		TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);  		 
	}		 	
}

定时器的基本定时功能就完成了。

3、定时器周期中断设计

避免博文过于冗长,具体代码详见下篇博文。
程序代码

三、高级定时器

1、定时器的输出比较功能

定时器的输出比较功能框图如下
在这里插入图片描述定时器输出比较的作用:
总的来说,通过定时器的外部引脚对外输出控制信号。
有冻结、将通道(x=1,2,3,4)设置为匹配时输出有效电平、将通道X设置为匹配时输出无效电平、翻转、强制变为无效电平、强制变为有效电平、PWM1和 PWM2这八种模式。
其中 PWM模式最为常用。

1、PWM输出模式

PWM有两种模式,如下图。
在这里插入图片描述
PWM输出就是对外输出脉宽(即占空比)可调的方波信号,其中有两个关键的影响因素。
1)信号频率由自动重装载寄存器(ARR)的值决定。
2)占空比由比较寄存器CCR的值决定。
接下来我们就来讲解一下PWM的输出原理。

PWM从概念上理解,也就是脉冲宽度的调制。如下图就是一个PWM的方波信号图,凸起部分可以理解为高电平(1),凹陷部分可以理解为低电平(0)。
一个周期 = 一段高电平时间+一段低电平时间。多个周期的高低电平就是我们要输出的PWM波。

我们知道这种连续的PWM方波的输出是周期性变化的,并且单个周期具有高低电平之分。
相应的我们就可以理解占空比的概念,占空比就是高电平时间/单个周期的时间。
在这里插入图片描述(图一)

那么,我们咋样改变占空比呢?或者说在单个PWM周期,何时输出高电平和低电平。(参考图二)
我们知道,PWM的输出是依靠定时器的通道产生的,定时器自然有时间控制的功能,而这一功能的实现依赖于定时器中由寄存器组成的内部结构。大致结构图参照文章开头。

在图二中,当计数器是递增模式时。递增计数模式下,计数器(CNT)从0开始计数,每来一个CK_CNT脉冲计数器就增加 1,直到计数器的值与自动重载寄存器ARR值相等,然后计数器又从0开始计数并生成计数器上溢事件,计数器总是如此循环计数。
在图中,CCR就决定了高低电平的输出,当CNT<CCRx时,输出低电平;当CNT>CCRx时,输出高电平。这样便连续地输出周期性的PWM波。

由此可见,改变 CCRx的值,就可以改变 PWM 输出的占空比,改变 ARR 的值,就可以改变 PWM 输出的频率,这就是 PWM 输出的原理。
在这里插入图片描述(图二)

2、四路PWM输出控制电机程序

由于不想博文过于冗长,具体代码详见这篇博文。
程序代码


2、定时器的输入捕获功能

后续博文将以运用实例的形式给出。
以编码器测速为例,详情可见这篇博文,编码器原理及测速方法。


http://www.niftyadmin.cn/n/931504.html

相关文章

8、两种典型微处理器介绍

微处理器将计算机中央处理器的所有构成组件整合在一起&#xff0c;集成在一个硅芯片上——诞生于1971年&#xff0c;它的诞生有着很好的开端&#xff1a;第一个微处理器&#xff0c;即Intel4004系列&#xff0c;包括2300个晶体管。到现在&#xff0c;大约三十年过去了&#xff…

定时器输出PWM控制电机(程序)

电机控制程序的三方面要点&#xff1a; 一、定时器的输出通道设置 二、电机频率的设定 三、占空比输入函数的设计 对于电机来说&#xff0c;转速与转向是最重要的表现。这里的程序是针对四个直流无刷电机来编写的。 控制四个电机&#xff0c;是需要电机驱动板的&#xff0c;因…

空间谱专题16:间距选取分析

作者&#xff1a;桂。 时间&#xff1a;2017-11-01 23:26:30 链接&#xff1a;http://www.cnblogs.com/xingshansi/p/7769153.html 前言 本文主要分析布阵间距选取依据&#xff0c;个人观点&#xff0c;仅供参考。 一、问题描述 对于空间谱测向&#xff08;以MUSIC算法为例&a…

BZOJ1086 [SCOI2005]王室联邦 【dfs + 贪心】

题目 “余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省&#xff0c;每个省都由他们王室联邦的一个成 员来管理。他的国家有n个城市&#xff0c;编号为1..n。一些城市之间有道路相连&#xff0c;任意两个不同的城市之间有且仅有一条 直接或间接的道路。为了…

STM32之周期中断设计(程序)

详细代码如下&#xff1a; my_pit.c #include "my_pit.h"//------------------------------------------------------------------------------------------------------------------- // brief 定时器周期中断 // param timern 定时器通道 // p…

当onmousedown、onmouseup、onclick同时应用于同一个标签节点Element

https://www.cnblogs.com/webflash/archive/2010/01/05/1639306.html 转载于:https://www.cnblogs.com/maidongdong/p/8191307.html

Spark MLlib架构解析(含分类算法、回归算法、聚类算法和协同过滤)

Spark MLlib架构解析 MLlib的底层基础解析 MLlib的算法库分析 分类算法   回归算法 聚类算法 协同过滤 MLlib的实用程序分析从架构图可以看出MLlib主要包含三个部分&#xff1a; 底层基础&#xff1a;包括Spark的运行库、矩阵库和向量库&#xff1b; 算法库&…