欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 新车 > 51单片机STC89C52RC——6.2 定时器

51单片机STC89C52RC——6.2 定时器

2024/10/25 4:20:00 来源:https://blog.csdn.net/oopxiajun2011/article/details/139885821  浏览:    关键词:51单片机STC89C52RC——6.2 定时器

        

一,定时器介绍

        STC89C51RC/RD+系列单片机的定时器0和定时器1,与传统8051的定时器完全兼容,当在定时器1做波特率发生器时,定时器0可以当两个8位定时器用。
        STC89C51RC/RD+系列单片机内部设置的两个16位定时器/计数器TO和T1都具有计数方式和定时方式两种工作方式。对每个定时器/计数器(TO和T1),在特殊功能寄存器TMOD中都有一控制位―CT来选择TO或T1为定时器还是计数器。定时器/计数器的核心部件是一个加法(也有减法)的计数器,其本质是对脉冲进行计数。只是计数脉冲来源不同:如果计数脉冲来自系统时钟,则为定时方式,此时定时器/计数器每12个时钟或者每6个时钟得到一个计数脉冲,计数值加1;如果计数脉冲来自单片机外部引脚(TO为P3.4,T1为P3.5),则为计数方式,每来一个脉冲加1。
        当定时器/计数器工作在定时模式时,可在烧录用户程序时在STC-ISP编程器中设置(如下图所示)是系统时钟/12还是系统时钟/6后让TO和T1进行计数。当定时器/计数器工作在计数模式时,对外部脉冲计数不分频。

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行

二,四种工作模式

STC89C52的T0和T1均有四种工作模式:     

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

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

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

模式3:两个8位计数器

模式1:

此模式下,定时器配置为16位定时器/计数器,由TL0的8位和TH0的8位所构成。TL0的8位溢出向TH0进位,THO计数溢出置位TCON中的溢出标志位TF0。
 

SYSclk:系统时钟,即晶振周期,本开发板上的晶振为12MHz

那么1毫秒 溢出一次的晶振次数怎么计算呢?

STC89C51RC/RD+系列单片机的定时器有两种计数速率:一种是12T模式,每12个时钟加1,与传统8051单片机相同;另外一种是6T模式,每6个时钟加1,速度是传统8051单片机的2倍。TO的速率在烧录用户程序时在STC-ISP编程器中设置。
 

STC89C52RC 的时钟频率是12MHz。

12MHz就是 1秒钟 晶振次数 是 12000000次,

12000000/12/1000(毫秒)=1000  (次/毫秒)

也就是说我们 要让定时器没1毫秒溢出一次,就得让晶振震动1000次后溢出。而溢出的时候TH0和TL0 合并起来的值是65536

所以我们把 定时器的初始值TH0和TL0的合并值设置为TIMS=65536-1000=64536

赋值

TL0=64535%256;(TL0=TIMS; [TL0只有8位,所以高位不会赋值过去,只有地位有效])

TH0=64536/256;(TH0=TIMS>>8;TH0也只有8位,TIMS右移8位后然低位溢出,高位就自动在低位了

每次中断发生后,都需要重新将TH0和TL0重新初始化。(在中断函数中重新赋值TH0和TL0)

 

三,如何开启定时器/计数器中断

3.1 开启中断 interrupt 1 (定时器Timer0/计数器 触发中断 实现LED闪烁)

如下图。要开启标红的这一路。配置还是比较多。不要嫌麻烦。挨着来。走一遍后,你会觉得像是打开了任督二脉。

按照图,还是从下往从右往左一次配置。

PX0: 优先级系统默认是最高级,不管

EA:全局中断开关合上  EA=1

ET0:允许Timer0/TF0 的中断进入。ET0=1;

我们再单独分析定时器器/计数器,

TR0:定时器开始运行;TR0=1;

TMOD:采用模式1(16位)

#include <REGX52.H> 
/*宏定义定时器的初始值*/
#define TIMS (65536-12000000/12/1000)
unsigned int count=1000;//计数器  默认1000
void main()
{TMOD=0x01;	//设置模式1TL0=TIMS;	//设置定时器的低8位TH0=TIMS>>8;//设置定时器的高8位TR0=1;		//让定时器开始运行ET0=1;		//允许定时器发生中断溢出EA=1;		//打开全局中断while(1);	//主程序停止在此
}/*** 函    数:定时器中断函数* 参    数:无* 返 回 值:无*/
void timer0_interrupt() interrupt 1
{TL0=TIMS;		//重新初始化低位TH0=TIMS>>8;	//重新初始化高位if(count--==0)	//1毫秒*1000=1秒{	count=1000;	//重置计数P2_0=!P2_0;	//第一个LED 每秒熄亮一次}
}

效果 

 

3.2 开启中断 interrupt 3 (定时器Time1/计数器 触发中断 实现LED闪烁)  

还是模式1,同样的,只是几个开关的名字变了

 

PX0: 优先级系统默认是最高级,不管

EA:全局中断开关合上  EA=1

ET1:允许Timer0/TF0 的中断进入。ET1=1;

TR1:定时器开始运行;TR1=1;

TMOD:采用模式1(16位)不过这里和上面有区别,要设置为0x10

#include <REGX52.H> 
/*宏定义定时器的初始值*/
#define TIMS (65536-12000000/12/1000)
unsigned int count=1000;//计数器  默认1000
void main()
{TMOD=0x10;	//设置模式1TL1=TIMS;	//设置定时器的低8位TH1=TIMS>>8;//设置定时器的高8位TR1=1;		//让定时器开始运行ET1=1;		//允许定时器发生中断溢出EA=1;		//打开全局中断while(1);	//主程序停止在此
}/*** 函    数:定时器中断函数* 参    数:无* 返 回 值:无*/
void timer1_interrupt() interrupt 3
{TL1=TIMS;		//重新初始化低位TH1=TIMS>>8;	//重新初始化高位if(count--==0)	//1毫秒*1000=1秒{	count=1000;	//重置计数P2_0=!P2_0;	//第一个LED 每秒熄亮一次}
}

 效果 与上面一样

 

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com