问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

51单片机STC89C52RC定时器详解

创作时间:
作者:
@小白创作中心

51单片机STC89C52RC定时器详解

引用
CSDN
1.
https://m.blog.csdn.net/oopxiajun2011/article/details/139885821

一,定时器介绍

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;	//设置模式1  
    TL0=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;	//设置模式1  
    TL1=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 每秒熄亮一次  
    }  
}  

效果 与上面一样

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号