【89c51汇编语言】认识定时器并同时调用两个定时器实现小灯不同频率闪烁

  • Post author:
  • Post category:其他




定时器

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;
	 }
 }
 



版权声明:本文为fanfan0301原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。