0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

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

jf_58200326 来源:jf_58200326 作者:jf_58200326 2023-04-03 14:11 次阅读

前言


本文主要基于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灯闪烁。

总结

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

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6036

    文章

    44555

    浏览量

    634902
  • 中断
    +关注

    关注

    5

    文章

    898

    浏览量

    41482
  • 定时器
    +关注

    关注

    23

    文章

    3247

    浏览量

    114753
  • STM32F103
    +关注

    关注

    33

    文章

    477

    浏览量

    63626
  • 延时函数
    +关注

    关注

    0

    文章

    25

    浏览量

    10018
收藏 人收藏

    评论

    相关推荐

    STM32 SYSTICK定时器常见问题

    我们知道,STM32库函数里通常使用来自内核的系统定时器SYSTICK作为时基,实现计数延时。一般来讲,ST公司提供的库函数里将SYSTICK定时器
    发表于 09-13 16:20 3043次阅读

    如何利用定时器编写精确的延时函数

    什么是定时器/计数??AT89C51的定时器/计数器具有哪些特性参数?如何利用定时器编写精确的延时
    发表于 09-30 06:00

    SysTick定时器是如何利用中断去实现延时函数

    SysTick定时器是什么?SysTick定时器是如何利用中断去实现延时函数呢?
    发表于 11-24 06:13

    51单片机定时器中断例程

    这个两个rar文件是关于定时器0使用的例子, 也是我第一次使用定时器0做的实验程序: 1. T0_ASM.rar, (带中文注释的C51语言例程), 利用
    发表于 05-26 17:06 397次下载

    stm32定时器中断程序

    STM32的定时器是个强大的模块,定时器使用的频率也是很高的,定时器可以做一些基本的定时,还可以做PWM输出或者输入捕获功能。 以下是进行stm32
    发表于 10-12 16:59 1.3w次阅读

    基于STM32定时器实现毫秒延时函数

    STM32定时器包含基本定时器、通用定时器和高级定时器,其中TIM6和TIM7是STM32当中的基本定时
    发表于 10-12 15:54 2.5w次阅读
    基于STM32<b class='flag-5'>定时器</b>实现毫秒<b class='flag-5'>延时</b><b class='flag-5'>函数</b>

    51单片机中断嵌套,定时器延时

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档51单片机中断嵌套,定时器延时前言一、如何做到定时器延时?二、如何做到外部
    发表于 11-20 17:06 17次下载
    51单片机<b class='flag-5'>中断</b>嵌套,<b class='flag-5'>定时器</b><b class='flag-5'>延时</b>

    "外部中断,定时器中断的理解"

    外部中断外部中断一般是由计算机外设发出的中断请指求,如:键盘中断、打印机中断定时器
    发表于 11-22 13:21 16次下载
    "外部<b class='flag-5'>中断</b>,<b class='flag-5'>定时器</b><b class='flag-5'>中断</b>的理解"

    通用定时器实现STM32单片机微秒级延时函数

    一、前言在实际应用中,经常用到延时函数,而HAL库的延时函数是毫秒级的,虽然可以自行修改,但该函数使用的地方较多,修改不慎可能会引起其他问题
    发表于 11-24 18:51 20次下载
    通用<b class='flag-5'>定时器</b>实现STM32单片机微秒级<b class='flag-5'>延时</b><b class='flag-5'>函数</b>

    STM32F4: Systick滴答定时器-延时函数讲解(五)

    Systick定时器基础知识讲解Systick相关寄存函数讲解delay延时函数讲解(Systick应用)(借鉴正点原子网课)(一)Sy
    发表于 12-01 15:21 15次下载
    STM32F4: Systick滴答<b class='flag-5'>定时器</b>-<b class='flag-5'>延时</b><b class='flag-5'>函数</b>讲解(五)

    SysTick 定时器

    的SysTick定时器来实现延时,可以不占用系统定时器,节约资源。由于SysTick是在CPU核内部实现的,跟MCU外设无关,因此它的代码可以在不同厂家之间移植。本 章 将 使用系统滴答定时器
    发表于 12-05 14:51 9次下载
    SysTick <b class='flag-5'>定时器</b>

    (指南者)(二)寄存定时器中断

    (指南者)(二)寄存定时器中断寄存器定时器时钟定时器寄存0110代码
    发表于 12-23 19:19 0次下载
    (指南者)(二)寄存<b class='flag-5'>器</b>、<b class='flag-5'>定时器</b>和<b class='flag-5'>中断</b>

    定时器中断是什么意思,定时器中断的工作原理

    定时器中断是由单片机中的定时器溢出而申请的中断。51单片机中有两个定时器T0和T1。STM32中共有11个
    的头像 发表于 07-23 09:45 6160次阅读

    定时器中断程序怎么写

    达到预定的定时时间时,它会产生一个中断信号,称为定时器中断。在本文中,我们将详细了解如何编写定时器中断
    的头像 发表于 09-01 10:17 1959次阅读

    RA2E1定时器带死区互补PWM中断延时问题分析

    RA2E1定时器带死区互补PWM中断延时问题分析
    的头像 发表于 10-27 10:56 746次阅读
    RA2E1<b class='flag-5'>定时器</b>带死区互补PWM<b class='flag-5'>中断</b><b class='flag-5'>延时</b>问题分析