关闭

女兔帮

51单片机入门第四课:定时器

更新时间:2025-02-18 21:56:39 浏览:

目录

Part1:定时器介绍

回想一下之前写的程序,在实现延时这一功能时,我们使用了delay() 函数,这个函数并没有采用任何外设,只是写了两个循环嵌套,让cpu计数,当计数完成也就代表延时结束,简单点说就是让cpu通过不停的计数来消耗时间,所以这种方式有个很大的弊端,就是当cpu “死跑” 延时的时候,是做不了其他事情的,这个时候就需要一个额外的工具来帮助cpu完成计时,这就是定时器的作用。举个例子,比如你想在十分钟后做某件事,如果身边没有任何工具的话,你只能自己默数600秒,而你在数数的时候是肯定不能分心做其他事情的哈,而如果你身边有块表,那就可以定一个十分钟后的闹钟,让它帮你计时,在这十分钟期间你就可以放心地做其他事情了。除此之外定时器还有一些其他作用,比如用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。

传统51单片机有3个定时器(简称T0,T1,T2),不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的。下面我们来学习51单片机最常用的片上外设——定时器。

Part2:定时器的工作模式与流程

的定时器T0和T1均有4种工作模式:

模式0:13位定时器/计数器

模式1:16位定时器/计数器 (常用)

模式2:8位自动重装模式

模式3:两个8位计数器

本节只介绍模式1:

首先定时器工作时主要分成三个步骤:时钟 → 计数 → 中断

51单片机入门第四课:定时器(图1)

可以看到,计数器里有两个时基单元,TL0(低8位)和 TH0(高8位)总共16位,所以叫16位定时/计数器,它最多可以计数 2^16=65535次。

计数器由时钟提供脉冲信号,经过分频器,每来一次脉冲计数+1,我们可以先设置一个计数器的初值 x,当计次超过65535时,下一个脉冲就会产生溢出,触发溢出中断,程序可以捕获到这个中断,就可以得知此次经历了(65535-x+1)us,这样就完成了一次定时。举个例子:我们可以把初值定位64535,这样到溢出值65535还需计数1000次,需要,这就是个1ms的定时器。

达到我们想要的计数值后,计数溢出就会进入中断,手册上关于中断的定义是这样说的:中断系统是为使 CPU 具有对外界紧急事件的实时处理能力而设置的。当中央处理机 CPU 正在处理某件事的时候外界发生了紧急事件请求,要求 CPU 暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。

51单片机入门第四课:定时器(图2)

可以看到中断并不会影响主程序的内容,可以理解为在主程序执行的过程中加急处理一项任务,这些任务也有轻重缓急之分,所以中断也会有优先级的高低之别,本篇介绍的定时器0的中断优先级排在第二,仅次于外部中断0。不同的中断会进入不同的入口通道,在程序里用中断号来区分不同类型的中断服务程序。

51单片机入门第四课:定时器(图3)

如何使用定时器 1.配置寄存器

定时器的相关两个寄存器如下:依然是STC官方手册里的表,TCON就是 “Timer ” 的意思,也就是定时器控制寄存器,TMOD就是 “Timer Mode”的意思,也就是定时器模式寄存器。

(1)先配置这个TMOD寄存器,定时器1的不用管所以只看低四位,门控端GATE直接给0就可以,C/T也给0,让系统时钟做脉冲源。我们想让定时器工作在哪个模式要配置M1和M0两位,具体参考下面这张图:

51单片机入门第四课:定时器(图4)

定时器0的工作模式由这两位共同决定,那我们需要定时器工作在16位定时器模式,所以M1=0,M0=1。TMOD寄存器是不可以位寻址,只能整体赋值,高4位为定时器1的部分,随便给任何值都可以,因为后面压根就不会进到中断,就都给它置0吧,这样TMOD的8位就是0000 0001也就是TMOD=0x01。

(2) 再配置这个TCON寄存器,TF1和TR1是定时器1的不用管他,TF0上面说了是中断允许标志位,在初始化的时候应先对其清零,TR0手册里叫定时器0运行控制位,我们给他置1,这个IE0和IT0都不需要配,因为上面的门控端GATE已经置0,所以IE0和IT0并不会影响。TCON寄存器是可以进行位寻址的,所以直接单独赋值即可:TF0=0,TR0=1,只需要配置这两位。

(3)接下来是配置计数器TL0和TH0,给这高8位和低8位都要设置好初值,就拿1模式为例,那初值就要设置为64535,2的8次方是256,想要取出64535的高8位就可以用 64535 / 256,低8位就是64535 % 256,这个原理就和十进制取高低位一样,只不过十进制 / 和 % 的是10的几次方,这里是2的几次方,那么TH0=64535 / 256,TL0=64535 % 256。

这样整个流程就都配置好了!看似很多内容,实现在代码上不过几行。关于中断服务程序和其他一些详细的内容都放到了代码的注释里,我们直接来看代码吧,这里拿呼吸灯的例子:

2.定时器实现呼吸灯代码

#include 
 
//声明
void T0init();
unsigned int PWM_wanttime=0;			  //想要多长时间改变的占空比一次
unsigned int Breath_wanttime=0;		  //想要多长时间改变呼气或者吸气的值时间
unsigned int PWM_value = 0;				  //占空比的大小
bit Direct_flag = 0; 	              //LED的呼吸方向的开关
void main()
{
	T0init();
	while(1)
	{
    
	}	
}
/*********************************************************
* 函数说明 :1ms定时
*********************************************************/
void T0init()
{
    TMOD |= 0x01;	//设置定时器为工作方式1  
    TH0=0XFC;     //1ms定时,装入初值
    TL0=0X66;
    ET0 = 1;      //开定时器的中断
    TR0 = 1;      //开定时器
    EA = 1;       //开总中断
}
 
void Time0(void) interrupt 1
{
 
    TH0=0XFC;                           //1ms定时,装入初值
    TL0=0X66;
 
    PWM_wanttime++;			                //改变的占空比一次的标志
    Breath_wanttime++;		              //呼气或者吸气的时间改变的标志
 
    if(PWM_wanttime == PWM_value)      	//判断是否到了点亮LED的时候
        P2 = 0x00;                    	//点亮LED
    if(PWM_wanttime == 10)            	//当前周期结束
    {
        P2 = 0xFF;                    	//熄灭LED
        PWM_wanttime = 0;              	//重新计时,去改变占空比
    }
 
 
    if((Breath_wanttime == 200) && (Direct_flag == 0))	  //200ms 改一次占空比,占空比每次增加10%
    {                               
        Breath_wanttime = 0;
        PWM_value++;				                              //改变占空比的值
 
        if(PWM_value == 9)                                //占空比更改方向
            Direct_flag = 1; 
    }
 
    if((Breath_wanttime == 200) && (Direct_flag == 1))	  //200ms 改一次占空比,占空比每次减少10%
    {                               
        Breath_wanttime = 0;
        PWM_value--;				                              //改变占空比的值
 
        if(PWM_value == 1)                                //占空比更改方向
            Direct_flag = 0; 
    }
}

呼吸灯效果:

呼吸灯

Part3:拓展计算机周期知识点(引用@)

51单片机的最小系统板上有一个12Mhz的晶振。那为什么是12Mhz为不是其他的频率呢?

计算机周期

想理解它就需要了解三个概念:时钟周期、指令周期和机器周期。

指令周期是取出一条指令并执行这条指令的时间。一般由若干个机器周期组成,是从取指令、分析指令到执行完所需的全部时间。

机器周期也称为CPU周期。在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段(如取指、译码、执行等),每一阶段完成一个基本操作。完成一个基本操作所需要的时间称为机器周期。一般情况下,一个机器周期由若干个时钟周期组成。

时钟周期也称为振荡周期,定义为时钟频率的倒数。时钟周期是计算机中最基本的、最小的时间单位。在一个时钟周期内,CPU仅完成一个最基本的动作。时钟周期是一个时间的量。时钟周期表示了SDRAM所能运行的**频率。更小的时钟周期就意味着更高的工作频率。

因此,晶振可以理解为单片机的 “心脏” ,它为单片机提供了时钟周期,晶振频率会直接影响时钟周期的大小,二者的关系为:时钟周期 = 1 / 晶振频率 无论你的晶振频率是多少,对于单片机来说,它内部都是固定的关系 ,在设计之初,由于51单片机性能和制程工艺等因素,出厂时把51单片机的机器周期严格的控制在12个时钟周期,指令周期一般是由1 2 4 个机器周期组成。

我们回到上面问题为什么晶振是12Mhz?我们计算下:时钟周期 = 1 / (12M) (s) = 1/ (s) = 1/12 (us),51单片机一个机器周期是12个时钟周期,即机器周期=12*1/12 (us) = 1 (us) ,这样执行1条指令的时间就控制在了1(us)、2(us)、4(us)。

Part4:结语

定时器部分刚接触来说可能比较难,本文也只简单介绍了其中定时器0的使用,关于中断优先级配置等更深入内容还请看江协科技的视频,在这里贴出一些定时器的教程以及应用链接,感兴趣可以点击学习:

[7-1] 定时器_哔哩哔哩

51单片机:中断系统(外部中断,定时器中断,串口通信)_51单片机串口中断-CSDN博客

【51单片机学习记录】PWM概述及其应用_单片机pwm-CSDN博客

【51单片机入门教程】51单片机利用pwm实现呼吸灯,了解占空比、程序优化方法_哔哩哔哩

基于51单片机制作频率计-测脉冲数法_51单片机信号频率计测量-CSDN博客

你可能感兴趣的