利用定时器中断代替延时函数(包含例程+原理思想)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

本文主要基于stm32f103系列讲解定时器中断进行计时代替延时函数,其中思路和原理同时适用于其他系列的单片机。


一、使用定时器中断的优缺点

相较于普通延时函数(delay),定时器中断计时无论是从代码的体量,还是使用,都要比延时函数更多更复杂,也更难理解。既然延时函数如此便捷,那我们又为什么不使用它呢?

首先在使用延时函数时,程序会停止在延时函数的位置,直到延时结束,在一些简单程序,使用延时函数的影响确实可以忽略不计,但是过多的延时函数会使程序变得臃肿,编译执行时间大大增加,程序的精度会下降,例如利用按键控制led灯时,led灯会不受按键控制,出现时灵时不灵的情况,这种情况就是延时函数使用过多造成的,更严重的甚至会造成单片机宕机。

所以,为了避免这种情况的发生,我们可以使用定时器中断来代替延时函数,下面是我个人的一些理解和认识,如有不足,欢迎指正。

二、使用步骤

1.原理思路

首先,我们需要配置一个定时器,stm32一般选用通用定时器即可,我们可以利用定时器初始化函数设定定时器计时一次的时间,公式如下:

定时时间=(arr+1)(psc+1)/Tclk

其中arr为自动重装载值,psc为预分频系数,TCLK为时钟频率,例如:TCLK=72MHz,那么psc=71,所以可以理解为时间就是(arr+1)微妙,那么如果我想定时1ms,arr取999即可(arr,psc为定时器初始化函数形参)。

当定时器的计数器计数到自动重装载值时,进入中断服务函数,这时我们需要设置一个标志位(flag)和作为计数用的值(count),每次进入中断count执行自加或自减,当其自加或自减到设置的数值时,标志位反转。 

例如:定时200ms,已知1ms进入一次中断,标志位flag初始值为0,那么让count自加到200,因为每次自加是1ms,自加两百次就是200ms,这时flag置1表示到达200毫秒并可以执行相关程序。

2.相关代码

(1).定时器初始化

(这里我初始的是TIM2)

TIMER.H

#ifndef __TIMER_H
#define __TIMER_H

#include "sys.h"
#include "stm32f10x_tim.h"

void TIM2_Int_Init(u16 arr,u16 psc);//通用定时器的初始化函数;arr:自动重装载值psc:预分频系数


#endif

TIMER.C 

#include "TIMER.h"


void TIM2_Int_Init(u16 arr,u16 psc)//通用定时器3的初始化函数
{
	//定义相关结构体
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStrue;//定义一个定时器初始化的结构体
	NVIC_InitTypeDef NVIC_InitStrue;//定义中断优先级初始化的函数
	
	//使能定时器时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//使能通用定时器3的时钟
	
	//设置并初始化定时器TIM2
	TIM_TimeBaseInitStrue.TIM_CounterMode=TIM_CounterMode_Up;//计数模式设置为向上计数
	TIM_TimeBaseInitStrue.TIM_Period=arr;//计数器模式为向上计数时,定时器从0开始计数,超过arr    
                                         //触发定时中断服务函数
	TIM_TimeBaseInitStrue.TIM_Prescaler=psc;//预分频系数,决定每一个计数的时长
	TIM_TimeBaseInitStrue.TIM_ClockDivision=TIM_CKD_DIV1;//一般不使用,默认为TIM_CKD_DIV1
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStrue);//根据参数初始化定时器TIM3

	//使能定时器中断
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//使能TIM3的中断,中断模式为更新中断
	
	//初始化定时器中断,定时器中断优先级设置
	NVIC_InitStrue.NVIC_IRQChannel=TIM2_IRQn;//中断通道设置为TIM3
	NVIC_InitStrue.NVIC_IRQChannelCmd=ENABLE;//使能中断
	NVIC_InitStrue.NVIC_IRQChannelPreemptionPriority=1;//抢占优先级为1级
	NVIC_InitStrue.NVIC_IRQChannelSubPriority=1;//响应优先级为1级
	NVIC_Init(&NVIC_InitStrue);//根据参数初始化中断寄存器
	
	//使能定时器
	TIM_Cmd(TIM2,ENABLE);//使能通用定时器TIM2
}

(2).stm32f10x_it.c(该文件专门用于存放中断服务函数) 


#include "stm32f10x_it.h"


extern	u8 flag;//标志位

void TIM2_IRQHandler()
{
	static u8 count;


  if(TIM_GetITStatus(TIM2, TIM_IT_Update)==1) //当发生中断时状态寄存器(TIMx_SR)的bit0会被硬件 
                                              //置1
	{
		if(count--==0)
		{
			count=20;
			flag=1;
		}

		TIM_ClearITPendingBit(TIM2, TIM_IT_Update); //状态寄存器(TIMx_SR)的bit0置0
	}
}

(3).主函数main.c

#include "stm32f10x.h"
#include "stm32f10x_conf.h"
#include "sys.h"

u8 flag=0;


int main(void)
{
	delay_init();					//初始化延时函数
	LED_Init();						//初始化led灯
	TIM2_Int_Init(9999,71);			//定时10ms进入一次中断

    while(1)
    {
            if(flag==1)    //标志位置一代表一次定时完成
			{
				PAout(2)=~PAout(2);    //led2取反
				flag=0;                //标志位置0,再次计时(该程序设置一次定时为200ms)
			}
    }
}

 3.效果:

每隔200msLED灯闪烁。


总结

以上是本人对定时器中断的一些认识(本人小白),其中有些地方讲解不到位,还望各位指正,欢迎评论区留言。

  • 13
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
stm32f407 定时器例程是针对STM32F407系列微控制器的定时器功能的一个示例代码。通过使用定时器,我们可以实现诸如延时、定时触发中断、PWM等功能。 在使用stm32f407 定时器例程之前,我们需要先配置定时器的工作模式、时钟源和频率等参数。具体步骤如下: 1. 引入头文件和库文件:在代码开头引入相关的头文件和库文件,以便后续使用定时器相关的函数和宏定义。 2. 配置定时器:使用相关函数配置定时器的模式、时钟源和频率等参数。比如可以选择定时器的工作模式(如定时模式、输入捕获模式、输出比较模式等)、时钟源(内部时钟源、外部时钟源等)和定时器频率(如设置分频系数)。 3. 开启定时器:使用相关函数开启定时器。这样,定时器就开始按照配置的频率工作了。 4. 定时中断处理函数:如果需要定时触发中断,可以编写一个定时中断处理函数。当定时器满足设定的时间后,会自动触发中断,并执行中断处理函数。 5. 使用定时器:根据需求使用定时器。可以利用定时器进行延时操作,或者生成PWM信号等。具体操作可以根据具体需求进行编写。 6. 关闭定时器:在使用完定时器后,可以使用相关函数关闭定时器,以释放资源。 以上就是关于stm32f407定时器例程的大致流程。具体的实现步骤和代码可以参考ST官方提供的例程或者相关教程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值