STM32学习笔记之定时器中断代替延时函数实现更精准计时(延时处理)

STM32学习笔记---------------------------普通延时与定时器延时哪个更好

不知不觉距离上一次发文已经过了两个月了,期间经历了很多事情,也学到了很多知识点,本文也是继上一篇文章之后的学习记录,希望有不足之处能得到各位大神指点!

简要介绍延时

对于初学者来说,延时是一个很简单却又不简单的功能,对于一些普通的延时函数我了解到的大概有以下这些:

//毫秒级延时
void delay_ms(u16 time)//这个time是你自定义的时间长度,比如2ms时time = 2;3ms时time = 3等,以此类推
{
	u16  time_cnt_ms  = 0;//这里定义一个变量,计数
	while(time --)
	{
		time_cnt_ms   = 10000;//这个值可以通过示波器或者逻辑分析仪抓,实在不行自己掐着表用LED显示来判断
		while(time_cnt_ms  --);
	}
}

//微秒级延时
void delay_us(u16 time)
{
	u16  time_cnt_ms  = 0;
	while(time --)
	{
		time_cnt_ms   = 8;//这个我是按8位记一次随便定义的,最好根据逻辑分析仪或者示波器自己抓了再自定义
		while(time_cnt_ms  --);
	}
}

以上是普通的延时函数,在实际项目中其实这样做有很大的忌讳,第一这样做其实不太精准,当你调用上面延时函数多了用示波器或者逻辑分析仪抓就知道时间会有一定的误差,而以后的学习中对整个程序的运行时间可控性考虑是成为高级程序员必不可少的经理;第二这样做就相当于空耗CPU资源,让他停在这个递减计数中循环,后果严重点可能会直接烧毁元器件啥的。
所以我们有了一种精准一点的延时,既能精准计数,又能处理别的事情而不占用CPU太多资源。没错,我要说的就是利用定时器中断延时,下面贴出我对这方面的程序运用:

//首先我们要了解什么是系统时钟--------建议网上直接搜索,最好看你所用的芯片型号的规格书
//首先还是一如既往地固定套路   定时器初始化 ---> 定时器中断优先级--->定时器中断处理函数
void TIM3_init(u16 arr,u16 psc)//这里是定时器的初始化函数,初学者最好理解透(看规格书、看视频找资料等)   固定的套路
{
	*( volatile unsigned int *) 0x4002101C |= 1<<1;  //这里直接操作寄存器地址,当初为了更好的理解下面写法的道理找了很久
 	TIM3->ARR=arr;  	//设定计数器自动重装值 
	TIM3->PSC=psc;  	//预分频器设置
	TIM3->DIER|=1<<0;   //允许更新中断				
	TIM3->CR1|=0x01;    //使能定时器3
	NVIC_Init(1,3,TIM3_IRQn,2);//抢占1,子优先级3,组2		//这里中断优先级配置							 
}

uint16_t time = 0;//这个要在对应的头文件里设置外部能调用 extern uint16_t  time;
u8 flag_1ms = 0;//这个要在对应的头文件里设置外部能调用 extern u8  flag_1ms;
//定时器3中断服务程序	 
void TIM3_IRQHandler(void)
{ 		
	if(TIM3->SR&0X0001)//溢出中断
	{	                                         
			time++;
			flag_1ms = 1;
	}	
		
	TIM3->SR&=~(1<<0);//清除中断标志位 	    
}

void mission_1ms(void)//你可以定一个1ms的标志位,把1ms执行一次的函数都放到这里面来
{
	//1ms做一次某任务
	if(flag_1ms)
	{
		zuoaizuodeshi();
		jiaopeijiaoderen();
		tingxiangtingdege();
		kanxiangkandedianying();
		//.......等等;
	}
}

void mission_anytime(void)//也可以任意定时间做某事
{
	if(time >= 1)//每隔1ms做某事
	{
		time  = 0;//计数累加到某一个值清零一次
		zuoaizuodeshi();
		jiaopeijiaoderen();
		tingxiangtingdege();
		kanxiangkandedianying();
		//.......等等;
	}

		//注意以下情况:time用过一次了。上面已经把time清零了,所以下面的函数怎么加也加不到10,下面的函数是错误示范(不能同时用一个time,那么你可以在中断处理函数中再加一个time1,不过不能加太多,这样也会导致定时器中断处理任务太多超过定时的1ms)
		if(time >= 10)//每隔10ms做某事
	{
		time  = 0;//计数累加到某一个值清零一次
		zuoaizuodeshi();
		jiaopeijiaoderen();
		tingxiangtingdege();
		kanxiangkandedianying();
		//.......等等;
	}
}

int main (void)
{
	TIM3_init(1000-1,72-1);//这里根据对应定时器的自动重装载值和预分频值得到每1毫秒执行一次TIM3中断里的事情
	/*这个主要看你芯片的规格和晶振的那个,
	我的是72MHz的频率:那么720000/预分频值 = 10000Hz,也就是每秒频率变化10k次(从10000递减到0),那么每毫秒频率变化多少次?(1秒 = 1000毫秒,那么1ms的重装载值是多少?1000嘛,但是计数应该是从(1000-1)递减到0)*/
	while(1)
	{
		zuoaizuodeshi();
		jiaopeijiaoderen();
		tingxiangtingdege();
		kanxiangkandedianying();
		//.......等等;
		mission_1ms();//这里注意要在主函数中调用1ms任务函数
	}
}

夜深了,先简要介绍这两种常用的延时吧,预知后事如何,请听下回分解!!
以上就是作者现在对定时器的大致理解,或许理解还不到位或者还没见识到更高级的处理,需要大家多多指出和相互交流,最后送大家一副对联吧:有志者,事竟成,百二秦关终属楚;苦心人,天不负,三千越甲可吞吴。
本文不足之处希望大家多多指出,非常感谢。

你可能感兴趣的:(STM32学习)