2.定时器中断

STM32F429总共有14个:

高级定时器:TIM1 和TIM8
通用定时器:TIM2-TIM5,TIM9-TIM14
基本定时器:TIM6 和 TIM7

挂载的总线:高级定时器及TIM9-TIM11的时钟来自APB2,其他来自APB1

APB2:TIM1 和 TIM8 、TIM9-TIM11

APB1:TIM2-TIM5、TIM6 和 TIM7、TIM12-TIM14

定时器简介

STM32F429 的通用定时器包含一个 16 位32 位自动重载计数器( CNT),该计数器由可编程预分频器( PSC) 驱动。

STM32F429 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。

使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。

STM32F429 的每个通用定时器都是完全独立的,没有互相共享的任何资源。
STM32 的通用 TIMx (TIM2~TIM5 和 TIM9~TIM14)定时器功能包括:


  1.   16 位/32 位(仅 TIM2 和 TIM5)向上、向下、向上/向下自动装载计数器(TIMx_CNT),注意: TIM9~TIM14 只支持向上(递增)计数方式。

  2.   16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。

  3.   4 个独立通道(TIMx_CH14TIM9TIM14 最多 2 个通道),这些通道可以用来作为:

A.输入捕获
B.输出比较
C. PWM 生成(边缘或中间对齐模式) ,注意: TIM9~TIM14 不支持中间对齐模式
D.单脉冲模式输出

  1.   可使用外部信号( TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外
    一个定时器)的同步电路。

  2.   如下事件发生时产生中断/DMA( TIM9~TIM14 不支持 DMA):

    A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
    B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    C.输入捕获
    D.输出比较
    E.支持针对定位的增量(正交)编码器和霍尔传感器电路( TIM9~TIM14 不支持)
    F.触发输入作为外部时钟或者按周期的电流管理( TIM9~TIM14 不支持)


常用的寄存器

TIMx_CR1:(Control Register 1)控制寄存器1

TIM1 和 TIM8:
TIM2-TIM5:
TIM9-TIM12
TIM6 和 TIM7:
qq空间图片
不会做点进去就是图片的链接,好尴尬。

TIMx_CR2:(Control Register 2)控制寄存器2

分类同TIMx_CR1

TIMx_DIER:(DMA Interrupt Enable Register)DMA/中断使能寄存器

TIMx_PSC:(Prescaler)预分频寄存器

TIMx_ARR:(auto-reload register)重装载寄存器

该寄存器在物理上实际对应着 2 个寄存器,一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器在《 STM32F4xx 中文参考手册》里面被叫做影子寄存器。事实上真正起作用的是影子寄存器。 根
据 TIMx_CR1 寄存器中 APRE 位的设置:APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2 者是连通的;而 PRE=1 时,在每一次更新事件( UEV)时,才把预装载寄存器( ARR) 的内容传送到影子寄存器。

TIMx_SR:(status register)状态寄存器

步骤

  • 1) TIM3 时钟使能。

这里我们通过 APB1ENR 的第 1 位来设置 TIM3 的时钟,因为 Stm32_Clock_Init 函数里面
把 APB1的分频设置为 4了,所以我们的 TIM3时钟就是 APB1时钟的 2倍,等于系统时钟 ( 90M)。

  • 2) 设置 TIM3_ARR 和 TIM3_PSC 的值。

通过这两个寄存器,我们来设置自动重装的值,以及分频系数。这两个参数加上时钟频率就决定了定时器的溢出时间。

  • 3) 设置 TIM3_DIER 允许更新中断。

因为我们要使用 TIM3 的更新中断,所以设置 DIER 的 UIE 位为 1,使能更新中断。

  • 4) 允许 TIM3 工作。

光配置好定时器还不行,没有开启定时器,照样不能用。我们在配置完后要开启定时器,通过 TIM3_CR1 的 CEN 位来设置。

  • 5) TIM3 中断分组设置。

在定时器配置完了之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,以使能TIM3 中断。

  • 6) 编写中断服务函数。

在最后,还是要编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,我们这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0,来清除该中断标志

示例代码

  • 寄存器
/************************/
//C文件内容
#include "tim3.h"


void TIM3_IRQHandler(void)
{
	if (TIM3->SR&0x0001)	//溢出中断		SR状态寄存器
	{
		LED0=!LED0;
	}
	TIM3->SR&=~(1<<0);			//状态寄存器清零
}


void TIM4_IRQHandler(void)
{
	if (TIM4->SR&0x0001)	//溢出中断		SR状态寄存器
	{
		LED1=!LED1;
	}
	TIM4->SR&=~(1<<0);			//状态寄存器清零
}


//通用定时器 3 中断初始化
//这里时钟选择为 APB1 的 2 倍,而 APB1 为 45M
//arr:自动重装值。
//psc:时钟预分频数
//定时器溢出时间计算方法:Tout=((arr+1)*(psc+1))/Ft us.
//Ft=定时器工作频率,单位:Mhz
//这里使用的是定时器 3!

void TIM3_Int_Init(u16 arr,u16 psc)
{							//0  	1  	 2     3  ...
	RCC->APB1ENR|=1<<1;		//TIM2 TIM3 TIM4 TIM5  ...
	TIM3->ARR=arr;			//自动重装载寄存器
	TIM3->PSC=psc;			//时钟预分频寄存器
	TIM3->DIER|=1<<0;		//允许更新中断
	TIM3->CR1|=0x01;		//控制寄存器1  使能定时器3
	MY_NVIC_Init(1,3,TIM3_IRQn,2);		//抢占1 ,子优先级 3
}

void TIM4_Int_Init(u16 arr,u16 psc)
{							//0  	1  	 2     3  ...
	RCC->APB1ENR|=1<<2;		//TIM2 TIM3 TIM4 TIM5  ...
	TIM4->ARR=arr;			//自动重装载寄存器
	TIM4->PSC=psc;			//时钟预分频寄存器
	TIM4->DIER|=1<<0;		//允许更新中断
	TIM4->CR1|=0x01;		//控制寄存器1  使能定时器3
	MY_NVIC_Init(2,3,TIM4_IRQn,2);		//抢占1 ,子优先级 3
}

/************************/
//头文件内容
#ifndef __TIM3_H_
#define __TIM3_H

#include "sys.h"
#include "led.h"

	void TIM3_Int_Init(u16 arr,u16 psc);
	void TIM4_Int_Init(u16 arr,u16 psc);

#endif

  • 库函数
/*********************/
//c文件

#include "timer.h"

TIM_HandleTypeDef TIM2_Handler;	
TIM_HandleTypeDef TIM3_Handler;	

//arr:自动重装载
//psc:时钟分频数
void TIM2_Init(u16 arr,u16 psc)	
{
	TIM2_Handler.Instance=TIM2;
	TIM2_Handler.Init.Prescaler=psc;
	TIM2_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;
	TIM2_Handler.Init.Period=arr;
	TIM2_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
	HAL_TIM_Base_Init(&TIM2_Handler);
	//使能
	HAL_TIM_Base_Start_IT(&TIM2_Handler);
}
void TIM3_Init(u16 arr,u16 psc)	
{
	TIM3_Handler.Instance=TIM3;
	TIM3_Handler.Init.Prescaler=psc;
	TIM3_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;
	TIM3_Handler.Init.Period=arr;
	TIM3_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;	
	HAL_TIM_Base_Init(&TIM3_Handler);
	//使能
	HAL_TIM_Base_Start_IT(&TIM3_Handler);
}

void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
{
	if (htim==&TIM2_Handler)
	{
		__HAL_RCC_TIM2_CLK_ENABLE(); //使能 TIM3 时钟
		HAL_NVIC_SetPriority(TIM2_IRQn,0,3); //设置中断优先级,抢占 1,子优先级 3
		HAL_NVIC_EnableIRQ(TIM2_IRQn); //开启 ITM3 中断
	}
	if (htim==&TIM3_Handler)
	{
		__HAL_RCC_TIM3_CLK_ENABLE(); //使能 TIM3 时钟
		HAL_NVIC_SetPriority(TIM3_IRQn,1,3); //设置中断优先级,抢占 1,子优先级 3
		HAL_NVIC_EnableIRQ(TIM3_IRQn); //开启 ITM3 中断
	}
}

//
void TIM2_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&TIM2_Handler);
}

//
void TIM3_IRQHandler(void)
{
	HAL_TIM_IRQHandler(&TIM3_Handler);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim==&TIM2_Handler)
	{
		LED1=!LED1;
	}
	
	if (htim==&TIM3_Handler)
	{
		LED0=!LED0;
	}
}

/************************************/
//头文件

#ifndef __TIMER_H__
#define __TIMER_H__


#include "sys.h"
#include "led.h"


	void TIM2_Init(u16 arr,u16 psc);
	void TIM3_Init(u16 arr,u16 psc);

#endif





  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值