STC89C52单片机定时器及中断系统的介绍以及代码示例

目录

 

一,定时器介绍

二,STC89C52定时器资源

三,定时器框图

四,定时器工作模式

五,中断系统及其流程

六,STC89C52中断资源

七,定时器与中断系统

八,相关寄存器的认识与配置

首先是定时器模式的配置(TMOD)

其次是中断系统的配置:

九,定时器时钟代码演示


一,定时器介绍

定时器介绍:

51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成

定时器作用:

(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作

为什么有Delay函数了还要用什么定时器呢?

(2)Delay函数在使用时,CPU是被占用的,不能进行别的操作。而定时器是和主程序同时进行的,可以替代长时间的Delay,提高CPU的运行效率和处理速度

二,STC89C52定时器资源

定时器个数:

3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源

注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的

三,定时器框图

看明白这个流程图哦

四,定时器工作模式

这里涉及到或门和与门的相关知识:

 以与门为例介绍一下简单的逻辑电路:

2个引脚都置为高电平的时候:

二极管与电阻没有压降,所以输出是5V。为高电平

如果2个引脚一个为高电平,一个为低电平的时候:

这个电路里面有电流流过,二极管与电阻有压降,所以输出的电压为0.7V,为低电平。

定时器的工作模式:

这里注意SYSclk的分频我们选择的是12分频,然后6分频是要在烧写软件里面手动确认,这是因为51单片机没有AUXR(辅助寄存器),所以没法设置分频。,如下图所示: 

还有关于定时器误差的计算:

这里的误差主要产生于系统频率与分频数的联系不大(倍数关系之类的),而且定时长度比较小,所以,这里计数1,相当于在12MHz计数:1x(12/fosc) ,fosc=11.0592MHz,所以得实际计时时间是:1.08506s,误差计算:(1.08506-1)/ 1=0.0851

五,中断系统及其流程

实际上单片机的优先级配置比较复杂这里我们只说两种优先级,方便理解(一般有四种优先级可以配置) 

六,STC89C52中断资源

中断源个数:8个(外部中断0、定时器0中断、外部中断1、定时器1中断、串口中断、定时器2中断、外部中断2、外部中断3)

中断优先级个数:4个

中断号

七,定时器与中断系统

定时器已经在之前的工作原理里面介绍了,下面主要是要介绍一下Interrupt是个什么东东?

传统的STC89C52的中断系统有4个优先级配置起来就比较复杂(主要是我们就配置了一个定时器中断,不是他优先还是谁优先,嘿嘿,所以我们不必搞得那么复杂)

这我们这我们之前在中断系统里面也聊过,但是还是给大家上图片看看:

这是传统的STC89C52的中断系统结构图

 为了方便讲解,这里使用的中断系统图是传统51单片机的中断系统结构图,都是一样的哈,只不过说传统51单片机只有2个优先级,看着比较明白,方便理解:

在这里我们配置的是定时器1,看T0哪一行就好了

八,相关寄存器的认识与配置

配置一句两句说不清楚,而且不是很权威,所以我引用手册上面的介绍

首先是定时器模式的配置(TMOD)

这里对几种工作模式进行简单的介绍:

一,13位定时/计数器方式

计数值为N和初值X关系:    X=8192-N /(12/fosc)

上次计数完,计数器值为0,要重复计数需重置初值。

(即在中断函数中将TH0,TL0,TH1,TL1置初值)

二,16位定时/计数器方式

计数值为N和初值X关系:    X=65536-N/(12/fosc)          {  X=65536-N*(fosc/12)  }

上次计数完,计数器值为0,要重复计数需重置初值。

如果上面的公式fosc与12不知道谁在分子谁在分母,那么其实可以假设fosc为11.0592Mhz,它比12Mhz计数慢(每个周期更大)可以以12Mhz为基准的话,在以11.0592Mhz为系统时钟的时候,相同的时间,11.0592Mhz计数少。所以就需要乘以一个小于1的数,即(fosc/12) 

三,8位自动重置定时/计数器

四,8位定时/计数器(只有配置T0才能使用)

计数值为N和初值X关系:    X=256-N /(12/fosc)

上次计数完,计数器自动重置初值。不需用户重置。

在一,二,三,四中fosc为晶振频率,51单片机一般为12MHz或者11.0592MHz

我们在使用定时器的时候一般使用的是模式二,16位定时/计数器方式

这里来详细讲讲12分频的过程,12MHz的系统时钟经过12分频以后,其频率变为1MHz,自然知道他的周期为1us,即在一个周期内计数为1。  所以自然:X=65536-N。而如果系统时钟是11.0592MHz那么,12分频后的的频率为(11.0592/12.0000)MHz,周期为(12.0000/11.0592)us,所以有等比式:(12.0000/11.0592)us /(xus)=(1)/(?),其中x为想要定时的时长(单位us),(?)则是需要计数的值。

其次是中断系统的配置:

这里的IT1与IT0的配置中,对于低电平触发低电平触发可能会有些疑问:

低电平触发:

            低电平触发中断顾名思义,就是检测到引脚为低电平就触发,从而进入中断函数中处理这个中断,并且在高或低电平保持的时间内持续触发,假设是低电平触发,只要引脚为低电平时间内中断一直有效,那么就会一直进入中断,直到电平变化为高电平

低电平触发:

        数字电路中,数字电平从高电平(数字“1”)变为低电平(数字“0”)的那一瞬间叫作下降沿。  下降沿触发是当信号有下降沿时的开关动作,当电位由高变低而触发输出变化的就叫下降沿触发。也就是当测到的信号电位是从高到低也就是下降时就触发,叫做下降沿触发。

那么我们可以很好的理解两种触发:

上升沿触发 就是当电压从低变高时触发中断
下降沿触发 就是当电压从高变低时触发中断

        当然,上升沿与下降沿检测的是电平变化的一瞬间,就会产生中断,这个时间是us级别的,但是如果中断引脚检测到一直保持低/高电平,则无法产生下次中断,也就是中断只会触发一次,只有在下次电平发生变化时才会重新触发中断

对照着中断图一起看思路会比较清晰

如果实在看不明白,全部置1也是没有问题的(下面的代码优先级PT0置的是0表示默认优先级,我们置1也是没有问题的)

九,定时器时钟代码演示

下面的是定时器的寄存器的相关配置:

系统时钟为12MHz的情况,即fosc=12.00MHz,计数值为N和初值X关系:   X=65536-N/(12/fosc)公式就变成了X=65536-N

下面是中断函数的内容,包括:

1,重新设置定时器的TH0与TL0的初值,

2,一个计次计时的模块

3,最后是中断函数的主体部分也就是时,分,秒的进制关系(一般根据需求替换这一部分)

 源代码如下:

#include <REGX52.H>

/**
  * @brief  定时器0初始化,1毫秒@12.000MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)
{
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x18;		    //设置定时初值
	TH0 = 0xFC;		    //设置定时初值
	TF0 = 0;		    //清除TF0标志
	TR0 = 1;		    //定时器0开始计时
	ET0=1;
	EA=1;
	PT0=0;
}

/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=1000)//在中断函数中重新进行计次,这里是每1s进行一次相关操作,注意写中断函数时一定要和定时器配套写(即定时器的声明/初始化)
	{
		T0Count=0;
		
	}
}
*/
void Timer0_Routine() interrupt 1
//中断函数中不可以加LCD这样的耗时过长的语句,显示的工作交由main(),否则会有L15报错
{
	static unsigned int T0Count;
	TL0 = 0x18;		//设置定时初值
	TH0 = 0xFC;		//设置定时初值
	T0Count++;
	if(T0Count>=1000)//每1s进行一次相关操作
	{
		T0Count=0;
		miao++;	
		if(miao>=60){
		     miao=0,fen++;
		               }
						if(fen>=60){
						shi++;fen=0;miao=0;
							if(shi>=24)shi=0;
		     }
		 }
}

最后,小白一个,有什么不足的地方还请各位大佬指出,谢谢大家。

posted @ 2022-04-09 17:36  爱吃炸鸡的小猪  阅读(1064)  评论(0编辑  收藏  举报