认识定时器
定时器
89c51中有两个定时/计数器,分别是T0和T1。为了帮助更好的理解单片机的定时器原理,先来看一下什么是单片机的时钟周期以及机械周期。
时钟周期(振荡周期)和机械周期
晶振是组成单片机最小系统的基本单元,我们常称“晶振”为单片机的心脏,为单片机提供脉冲信号,基本时间单位。单片机工作时,是顺序地从ROM中取指令,然后一步一步地顺序执行。所以我们需要共用一个时间基准:单片机访问一次存储器的时间,称之为一个
机器周期
,—个机器周期包括12个
时钟周期
。单片机的
时钟周期
是晶振频率的倒数,这是单片机的基本时间单位。时钟频率越高,单片机运行速度越快。如果一个单片机外接了一个12MHz的晶振,那么它的时钟周期就是1/12us,它的一个机器周期是12×(1/12)us,也就是1us。
关系:时钟周期–>机械周期–>指令周期(比如DJNZ指令占用两个机械周期,LCALL指令占用四个机械周期)
定时/计数器相关的的寄存器(TMOD、TCON)
TMOD(不可位寻址,只能用字节方式设置工作方式)
TMOD的低四位控制定时器T0,高四位控制定时器T1。
GATE:选通控制位,GATE置0后只要对 TR0( TR1)置 1 就可启动定时器。
C/T: 置0即为定时器工作模式,置1即为计数器工作模式。
M1和M0决定了定时器有四种工作模式(我们常用工作模式1和工作模式2)
举个例子:设置T0为16为定时器计数模式,我们就要设置TMOD为0x01
中断控制寄存器TCON(可位寻址)
TF1: T1溢出标志。
进入中断服务程序后,由硬件自动清“0”,在查询方式下用软件清“0”。
TF0: T0溢出标志。
TR1: T1运行控制位。当TR1=1,T1开启。
TR0: T0运行控制位。当TR0=1,T0开启。
定时器工作模式1&工作模式2
工作模式1:16位定时/计数器
t = ( 2^16- 初值 ) × 机器周期
定时器为 16 位:TH0、TH1为定时器0和定时器1的高四位,TL0、TL1为定时器0和定时器1的低四位。若晶振频率为 12MHz,则方式 1 下的最大定时时间为 65.536 ms。即计数器初值设置为 0000H,经过 2^16=65536 个机器周期后定时器将产生溢出,故最长定时时间为 1μs× 65536= 65.536 ms。
工作模式2:8位定时器
t = ( 2^8 - 初值)×机器周期
方式 2 可在计定时器计满时自动装入初值。工作方式 2 把 16 位的定时器拆成两个 8 位定时器。 TL0 用作 8 位定时器。 TH0 用来保存初值,每当 TL0 计满溢出时,可自动将 TH0 的初值再装入 TL0 中,继续计数,循环重复。工作方式 2 的定时时间为 TF0 溢出周期。这种工作方式可省去用户软件中重装初值的程序,并可产生相当精度的定时时间,特别适合于产生周期性脉冲以及作为串行口波特率发生器,缺点是计数长度太小。
同时调用两个定时器实现小灯不同频率闪烁
题目要求:利用定时器0,使p1.0口输出1s的方波,并通过led显示。利用定时器1,使用查询方式,使P1.1口产生周期为500ms的方波,通过led闪烁进行显示。
汇编语言版:(运用了两种不同的方法实现:中断以及查询)
ORG 0000H ;起始地址源,在汇编语言源程序的开始通常都用一条ORG伪指令来规定程序的起始地
LJMP MAIN
;转移指令代码,在0000H开始的单元跳转进入main
ORG 000BH ;定时器0的地址,p.s.定时器1的地址为001BH
LJMP INTT0 ;设置中断入口
ORG 0100H
MAIN:MOV SP,#60H ;设置堆栈指针
MOV R3,#50 ;循环50次
MOV R4,#25 ;循环25次
MOV TMOD,#11H ;定时器0和定时器1选择16位定时器工作模式,即m1m0置01
MOV TH1,#0DCH
MOV TL1,#00H ;定时10ms
MOV TH0,#0DCH
MOV TL0,#00H;
SETB EA ;中断总开关开启
SETB ET0;定时器0中断开启
SETB TR0;启动定时器0
SETB TR1;启动定时器1
LOOP1:JNB TF1,LOOP1;如果定时器1溢出,即TF1=1,进入loop1
DJNZ R4,LOOP2;r4自减,并判断r4的值,如果r4=0,跳转进入loop2
CPL P1.0;取反,实现闪烁
MOV R4,#25;重设初始值
LOOP2:MOV TH1,#0DCH;定时10ms
MOV TL1,#00H
SJMP LOOP1;goto loop1
SJMP $;原地踏步
INTT0:;进入定时器0的中断
MOV TH0,#0DCH;定时10ms
MOV TL0,#00H
DJNZ R3,LOOP;r3自减,并判断r3的值,如果r3=0,跳转进入loop
CPL P1.0;
MOV R3,#50;
LOOP:
RETI;跳出中断
END
c语言版:
#include <reg51.h>
sbit led0 = P1^0;
sbit led1=P1^1;
void main(void)
{
TMOD = 0x11;
TH0 = 0xDC; //10MS
TL0 = 0x00;
TH1 = 0xDC; //10MS
TL1 = 0x00;
EA = 1;
ET0 = 1;
ET1=1;
TR0 = 1;
TR1 = 1;
while(1);
}
void T0_Interrupt() interrupt 1
{
static unsigned char cnt=0;//定义静态变量,记录循环次数
TH0 = 0xDC;
TL0 = 0x00;
cnt++;
if(cnt>=50)
{
led0 = ~led0;
cnt=0;
}
}
void T1_Interrupt() interrupt 3
{
static unsigned char num=0;
TH1 = 0xDC;
TL1 = 0x00;
num++;
if(num>=25)
{
led1 = ~led1;
num=0;
}
}