89C51单片机的定时计数功能由特殊功能寄存器TMOD和TCON共同控制。
TMOD没有位地址,不能进行位操作,其每位的名称和功能如下:
TMOD:GATE C/T1 M1 M0 GATE C/T1 M1 M0
D7 D6 D5 D4 D3 D2 D1 D0
GATE C/T1 M1 M0 控制定时计时器1;
GATE C/T0 M1 M0 控制定时计时器0;
GATE=0时,定时计数信号是T0脚状态(P3.4)或机器周期(C/T=0计机器周期,即定时,C/T=1,计T0脚的状态,即计数),计数开始开关是TR0(0关闭计数,1开始计数)。
GATE=1时,定时计数功能由T0脚(P3.4)或者机器周期确定(C/T=0计数机器周期,即定时,C/T=1,计数T0脚的变化状态,即计数),计数开始开关由TR0(0关闭计数,1开始计数)和INT0(管脚P3.2)共同确定。
M1M0是计数方式选择:计数在TH0和TL0进行。
00为方式0,13位(TH0的8位和TL0的低5位)二进制计数器,由0可数到2的13次方-1;
01为方式1,16位二进制计数器,由0可数到2的16次方-1;
10为方式2,8位二进制计数器,TH0放计数初值,计数在TL0进行,溢出后自动将
TH0中的初值装入TL0;
11为方式3,TH0是个8为计数器,HL0是个8位计数器。两个计数器相互独立。
T1和T0功能相同。
特殊功能寄存器TCON,可以位操作,但一般不用位地址,而用位的功能名称:
位地址:8FH 8EH 8DH 8Ch 8Bh 8Ah 89H 88H
TCON :TF1 TR1 TF0 TR0 IE1 IT1 IE0 IT0
D7 D6 D5 D4 D3 D2 D1 D0
TF0是T0计数标志位:定时计数溢出时,该位被自动置1,中断计数结束后自动清0.
TR0是计数开关,GATE=0时,TR0=1打开计数,0关闭。当GATE=1时,和INT0一起控制计数器打开,即GATE=1,TR0=1,INT0=1才可打开计数,否则关闭。
定时/计数时,由TH0 TL0的值开始加1计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式,中断请求由硬件给TF0置1,计数结束后,也就是中断结束后,自动将TF0清0。
/***************定时器定时50ms,在计数20下为1秒,显示60秒计时(查询模式)***********/
#include
#include
#define uchar unsigned char
#define uint unsigned int
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
int t,k,dat;
void delay(int ms)
{
while(ms--)
{
int i;
for(i=0;i<30;i++);
}
}
void Timer0()
{
if(TF0==1)//查询TF0为1,说明计数满了,计数结束。
{
t++;
TH0=0x3c;//这里是计数满后重新装入计数初值.也可TH0=(65536-5000)/256
TL0=0xb0;//计数溢出后再次计数从这里开始,也可TL0=(65536-5000)%256
/*如果先计算初值麻烦,还可以用16位二进制的最大值65536-定时计数次数赋值给TH0和TL0,例如定时40ms,需对机器周期计数4000下,可以
TH0=(65536-4000)/256;TL0=(65536-4000)%*/
TF0=0;
}
//清除溢出标志
}
void T1s()
{
if(t==20)//计数一次50ms,20次为1秒
{t=0;
dat++;
if(dat==60)//60次为1分钟
dat=0;
}
}
{
TMOD=0x01;
/*此设置(0000 0101)T0的GATE=0,C/T为0,M1M0为01。
GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
C/T=0,定时功能,计数机器周期的个数。
M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满
再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中
断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.
打开计数器0中断将ET0=1,EA=1 */
TH0=0x3c;//设置计数器计数初值50ms从3CB0H开始计数
TL0=0xb0;//第一次从这里的设置开始计数
TR0=1;
while(1)
{
Timer0();
T1s();
P0=yu[dat%10];
delay(1);
P2=0x01;
delay(1);
P2=0x00;
P0=yu[dat/10];
delay(1);
P2=0x02;
delay(1);
P2=0x00;
}
}
/*******定时/计数器0中断应用,按键没按一次数码管显示加1(中断模式)*************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
int k;
void delay(int ms)
{
while(ms--)
{
int i;
for(i=0;i<30;i++);
}
}
void ddd() interrupt 1
{
TH0=0xff;//这里是计数满后重新装入计数初值
TL0=0xfa;//计数溢出后再次计数从这里开始
delay(5);
if(TF0==0)//计数中断时TF0由硬件置1,响应中断并开始计数,计数产生溢出后自动清0,结束计数。
{ //所以,响应中断后,查询TF0的状态可以判断中断计数是否结束
if(k==99)
k=0;
else
k++;
}
}
{
TMOD=0x05;
/*此设置(0000 0101)T0的GATE=0,C/T为1,M1M0为01。
GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
C/T=1,计数功能,计数管脚T0(P3.4)的状态变化。
M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.打开计数器0中断将ET0=1,EA=1 */[page]
TH0=0xff;//设置计数器计数初值
TL0=0xfc;//第一次从这里的设置开始计数
ET0=1;
TR0=1;
EA=1;
while(1)
{
P0=yu[k%10];
delay(1);
P2=0x01;
delay(1);
P2=0x00;
P0=yu[k/10];
delay(1);
P2=0x02;
delay(1);
P2=0x00;
}
}
/******用查询模式计数
#include
#include
#define uchar unsigned char
#define uint unsigned int
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
int k;
void delay(int ms)
{
while(ms--)
{
int i;
for(i=0;i<30;i++);
}
}
void jishu()
{
if(TF0==1)//查询TF0,为1,说明计数满了,计数结束。
{
TH0=0xff;//这里是计数满后重新装入计数初值
TL0=0xff;//计数溢出后再次计数从这里开始
delay(5);
if(k==99)
k=0;
else
k++;
}
TF0=0; //清除溢出标志
}
{
TMOD=0x05;
/*此设置(0000 0101)T0的GATE=0,C/T为1,M1M0为01。
GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
C/T=1,计数功能,计数管脚T0(P3.4)的状态变化。
M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.打开计数器0中断将ET0=1,EA=1 */
TH0=0xff;//设置计数器计数初值
TL0=0xff;//第一次从这里的设置开始计数
TR0=1;
while(1)
{
jishu();
P0=yu[k%10];
delay(1);
P2=0x01;
delay(1);
P2=0x00;
P0=yu[k/10];
delay(1);
P2=0x02;
delay(1);
P2=0x00;
}
}
/**********************用定时中断设计秒表及显示****************************/
#include
#include
#define uchar unsigned char
#define uint unsigned int
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
};
int k,dat;
void delay(int ms)
{
while(ms--)
{
int i;
for(i=0;i<30;i++);
}
}
void ddd() interrupt 1
{
TH0=(8192-4000)-(8192-4000)%32;//这里是计数满后重新装入计数初值
TL0=(8192-4000)%32;//计数溢出后再次计数从这里开始
delay(5);
if(TF0==0)//计数中断时TF0由硬件置1,响应中断并开始计数,计数产生溢出后自动清0,结束计数。
{ //所以,响应中断后,查询TF0的状态可以判断中断计数是否结束
if(k==250)
{k=0;
dat++;}
else
k++;
//关闭T0计数器,TR0=0句不能在主程序中,要在查询函数或中断函数中,否则停不下来。
}
}
{
TMOD=0x00;
/*此设置(0000 0101)T0的GATE=0,C/T为1,M1M0为01。
GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
C/T=1,计数功能,计数管脚T0(P3.4)的状态变化。
M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.打开计数器0中断将ET0=1,EA=1 */
TH0=0xa3;//设置计数器计数初值
TL0=0x00;//第一次从这里的设置开始计数
ET0=1;
TR0=1;
EA=1;
while(1)
{
P0=yu[dat%10];
delay(1);
P2=0x01;
delay(1);
P2=0x00;
delay(1);
P2=0x02;
delay(1);
P2=0x00;
delay(1);
P2=0x04;
delay(1);
P2=0x00;
delay(1);
P2=0x08;
delay(1);
P2=0x00;
}
}
=====================================================
汇编语言编写的T0中断定时器
ORG 0000H
Ljmp main
ORG 000BH
Ljmp T0ZD
org 0100h
main:mov TMOD,#00h
mov TH0,#83h
mov TL0,#00h
mov r7,#00h
setb EA
setb ET0
setb TR0
mov dptr,#0300h
disp:mov 70h,r3
mov a,70h
mov b,#0ah
div ab
movc a,@a+dptr
mov P0,a
mov P2,#02h
nop
nop
mov P2,#00h
mov a,b
movc a,@a+dptr
mov P0,a
mov P2,#01h
nop
nop
mov P2,#00h
sjmp disp
T0ZD:mov TL0,#00h
mov TH0,#83h
cpl p1.7
cjne r7,#250D,zzz
mov r7,#00h
cjne r3,#60h,ddd
mov r3,#00h
ddd: inc r3
zzz: inc r7
reti
org 0300h
db 3fh,06h,5bh,4fh,66h,6dh,7dh,07h,7fh,6fh
end
===================================================
上一篇:用51单片机中断编写的4x4键盘程序
下一篇:关于51单片机双机通信
推荐阅读最新更新时间:2024-03-16 13:51