前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(十七)STM32——定时器

(十七)STM32——定时器

作者头像
小点点
发布2022-12-12 14:43:47
8760
发布2022-12-12 14:43:47
举报
文章被收录于专栏:小点点

目录

学习目标

内容

简介

定时器分类

定时器功能介绍

计时器模式

工作过程

内部时钟选择

寄存器

配置

代码

总结 


学习目标

        本节内容我们来介绍一下有关定时器的知识,其实这个定时器,和我们日常接触的定时器没有什么区别,都是到了一定的时间就去做指定的事情。和51单片机的定时器也没有很大区别,就是数量和功能明显变多了许多,那我们就开始吧!

内容

简介

        STM32F4 的定时器功能十分强大,有 TIME1 和 TIME8 等高级定时器,也有 TIME2~TIME5,TIM9~TIM14 等通用定时器,还有 TIME6 和 TIME7 等基本定时器,总共达 14 个定时器之多。我们今天就只介绍一下通用定时器,日后要用到其他定时器的话再来介绍。

定时器分类

        因为 STM32F4 的定时器非常之多,所以对定时器做了一个分类,分为高级定时器、通用定时器和基本定时器,其中通用定时器还细分了三类,都有各自的特点(功能逐渐变少),具体的功能如下,就不一一介绍了。(计数器模式到后面进行介绍)

定时器功能介绍

STM3 的通用 TIMx (TIM2~TIM5 和 TIM9~TIM14)定时器功能包括:         1)16 位/32 位(仅 TIM2 和 TIM5)向上、向下、向上/向下自动装载计数器(TIMx_CNT),注意:TIM9~TIM14 只支持向上(递增)计数方式。         2)16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~ 65535 之间的任意数值。         3)4 个独立通道(TIMx_CH1~4,TIM9~TIM14 最多 2 个通道),这些通道可以用来作为:                 A.输入捕获                 B.输出比较                 C.PWM 生成(边缘或中间对齐模式) ,注意:TIM9~TIM14 不支持中间对齐模式                 D.单脉冲模式输出         4)可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。         5)如下事件发生时产生中断/DMA(TIM9~TIM14 不支持 DMA):                 A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)                 B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)                 C.输入捕获                 D.输出比较                 E.支持针对定位的增量(正交)编码器和霍尔传感器电路(TIM9~TIM14 不支持)                 F.触发输入作为外部时钟或者按周期的电流管理(TIM9~TIM14 不支持)

        这么多的功能,我也没有一一使用过,我们今天只使用简单的计数和中断功能,也是51单片机中的基本功能。剩下的功能后面慢慢介绍。 

计时器模式

通用定时器可以向上计数、向下计数、向上向下双向计数模式。

  1. 向上计数模式:计数器从0计数到自动加载值(TIMx_ARR),然后重新从0开始计数并且产生一个计数器溢出事件。
  2. 向下计数模式:计数器从自动装入的值(TIMx_ARR)开始向下计数到0,然后从自动装入的值重新开始,并产生一个计数器向下溢出事件。
  3. 中央对齐模式(向上/向下计数):计数器从0开始计数到自动装入的值-1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器溢出事件;然后再从0开始重新计数。

        我们通俗一点来理解,以加载值为100为例子,向上计数模式就是从0数到100,产生一个信号,再次从0开始;向下计数模式就是从100数到0,产生一个信号,再次从100开始;而中央对齐,就是从0数到99,产生一个信号,再由99数到1,产生一个信号。再放一张图来给大家看一下。

        我们简单介绍一下向上计数模式的工作方式。 首先,需要使能(CNT_EN),然后计数器递增,直到设置的值,然后事件更新,中断标志也随着更新了。

工作过程

        这就是通用定时器的工作框图,每个部分的功能我都用不同颜色框选了起来,并在旁边写了一下功能,值得一说的是,关于时钟源的产生,通用定时器有四种方式。

  1. 内部时钟
  2. 外部引脚
  3. 内部触发输入口
  4. 外部通道 

内部时钟选择

        这边我们接入的是APB1时钟,是系统时钟通过4分频得到的。系统时钟是168M,所以APB1时钟就是42M的。而除非APB1的分频系数是1,否则通用定时器的时钟等于APB1时钟的2倍。所以CK_INT 就是82M的。

寄存器

        还是之前一样,寄存器部分我们不做详细介绍。 感兴趣同学可以自己去查看手册。

配置

        我们来介绍一下有关库函数配置的过程:

  • TIM3 时钟使能,我们需要使能APB1总线,所用函数如下所示:
代码语言:javascript
复制
 void RCC_APB1PeriphClockCmd(uint32_t RCC_APB1Periph, FunctionalState NewState); ///使能 TIM3 时钟

  • 初始化定时器参数,设置自动重装值,分频系数,计数方式等,这个是通过初始化函数来实现的,如下所示:
代码语言:javascript
复制
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;//这个需要配置一下这个结构体
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct) 

  • 设置 TIM3_DIER 允许更新中断。
代码语言:javascript
复制
 void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
 

  • TIM3 中断优先级设置。
代码语言:javascript
复制
 // 这个在中断介绍过,就不再介绍了
 

  • 允许 TIM3 工作,也就是使能 TIM3。
代码语言:javascript
复制
 void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
 

  • 编写中断服务函数。
代码语言:javascript
复制
// 这个是函数名,中断函数里的东西自己配置
void TIM3_IRQHandler(void)
 

代码

代码语言:javascript
复制
#include "timer.h"
#include "led.h" 

//通用定时器3中断初始化
void TIM3_Int_Init(u16 arr,u16 psc)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);  ///使能TIM3时钟 
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数
	TIM_TimeBaseInitStructure.TIM_Period = arr ;//arr:自动重装值。
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc ;//psc:时钟预分频数
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);//初始化TIM3
	
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断

	
	NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn; //定时器3中断
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0x01; //抢占优先级1
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0x03; //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	
	TIM_Cmd(TIM3,ENABLE); //使能定时器3
}

//定时器3中断服务函数
void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update) != RESET) //溢出中断
	{
		LED0=!LED0;//LED0翻转
	}
	TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清除中断标志位
}

代码语言:javascript
复制
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "timer.h"

int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);  //初始化延时函数
	LED_Init();				//初始化LED端口
    LED1= 0;
 	TIM3_Int_Init(5000-1,8400-1);	//定时器时钟84M,分频系数8400,所以84M/8400=10Khz的计数频率,计数5000次为500ms     
	while(1)
	{
		LED1=!LED1;//LED1翻转
		delay_ms(500);//延时200ms
	};
}

总结 

        本章讲解的是定时器的基础用法, 和之前51单片机类似,不过还是希望能够帮助到大家,谢谢各位的观看!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 学习目标
  • 内容
    • 简介
      • 定时器分类
        • 定时器功能介绍
          • 计时器模式
            • 工作过程
              • 内部时钟选择
                • 寄存器
                  • 配置
                  • 代码
                  • 总结 
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档