MCU 51-3定时器
阅读原文时间:2023年07月11日阅读:1

51定时/计数器简介

51单片机有2个16位定时器/计数器:定时器0(T0为P3.4)和定时器1(T1为P3.5)。这里所说的16位是指定时/计数器内部分别有16位的计数寄存器。

当工作在定时模式时,每经过一个机器周期内部的16位计数寄存器的值就会加1,当这个寄存器装满时溢出。 我们可以算出工作在定时模式时最高单次定时时间为 65535*1.085us=时间(单位us)

当工作在计数器模式时,T0(P3.4引脚),T1(P3.5引脚) 每来一个脉冲计数寄存器加1

定时器作用:可以用于精确事件定时,PWM脉宽调制,波形发生,信号时序测量的方面。

使用51定时/计数器步骤

(1)启动定时/计数器(通过TCON控制器)

(2)设置定时/计数器工作模式(通过TMOD控制器)

(3)查询定时/计数器是否溢出(读TCON内TF位)

51定时/计数器控制寄存器

TF1(T1溢出标志位):当定时/计数器T1溢出时由硬件置“1”TF1,向CPU发出中断请求,一直保持到CPU响应时,才由硬件清“0”(TF1也可以由程序查询清“0”)

TR1(定时器T1运行控制位):该位由软件置“1”或清零。TR1= 1就允许T1开始计数TR1=0时禁止T1计数。

TF0(T0溢出标志位)

TR0(定时器T0运行控制位),配置方法与T1相同。

IE1、IT1、IE0、IT0与定时/计数器无关,是控制外部中断的。

51定时/计数器工作模式寄存器(不可位寻址

bit7       控制T1,置“1”时只有在P3.3脚为高及TR1置“1”时才可以启动T1,置“0”时TR1为“1”就允许T1启动。

bit6       置“1”时T1做计数器,置“0”时T1做定时器。

当工作在计数器模式时,T0(P3.4引脚),T1(P3.5引脚) 每来一个脉冲计数寄存器加1

bit5~4   M1 M0

M1 = 0,M0 = 0时 工作模式0。13位定时器模式,这是为了与8048兼容而设计的。16位计数器只用了13位,即TH0的高8位和TL0的低5位,组成一个13位定时器/计数器。

M1 = 0,M0 = 1,工作模式1 此时由TH1、TL1寄存器组成16位计数器,TH1 为16位的高8位,TL1为16位的低8位,当这个16位计数 器加满时,T1溢出。TF1被硬件置“1”。

M1 = 1,M0 = 0,工作模式2,时8位自动重装定时器,当TL1溢 出时,将TH1的值自动装入到TL1中,TF1被硬件置“1”。

M1 = 1,M0 = 1,工作模式3,T1停止计数。

bit3~0 设置T0定时器的,和T1设置相同(除工作模式3)

定时器1:

/*定时器1,定时模式 工作模式1 16位计数器,
定时20秒后点亮LED1,数码管显示*/
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit we = P2^;
sbit du = P2^;

uchar code leddata[]={

            0x3F,  //"0"  
            0x06,  //"1"  
            0x5B,  //"2"  
            0x4F,  //"3"  
            0x66,  //"4"  
            0x6D,  //"5"  
            0x7D,  //"6"  
            0x07,  //"7"  
            0x7F,  //"8"  
            0x6F,  //"9"  
            0x77,  //"A"  
            0x7C,  //"B"  
            0x39,  //"C"  
            0x5E,  //"D"  
            0x79,  //"E"  
            0x71,  //"F"  
            0x76,  //"H"  
            0x38,  //"L"  
            0x37,  //"n"  
            0x3E,  //"u"  
            0x73,  //"P"  
            0x5C,  //"o"  
            0x40,  //"-"  
            0x00,  //熄灭  
            0x00  //自定义

                     };

void delay(uint z)
{
uint x,y;
for(x = z; x > ; x--)
for(y = ; y > ; y--);
}

void display(uchar i)
{
uchar shi, ge;
shi = i / ;//求模 i除以10取商的整数部分
ge = i % ;//求余 i除以10取余数部分

P0 = 0xff; //清除断码  
we = ;//打开位选  
P0 = 0xfe;//1111 1110 只选通第一位数码管  
we = ;    //关闭位选

du = ;    //打开段选  
P0 = leddata\[shi\];  
du = ;    //关闭段选  
delay();//延时5毫秒

P0 = 0xff;//清除断码  
we = ;    //打开位选  
P0 = 0xfd;//1111 1101  只选通第二位数码管  
we = ;    //关闭位选

du = ;//打开段选  
P0 = leddata\[ge\];  
du = ;    //关闭段选  
delay();//延时5毫秒  

}

void main()
{
uchar a; //50次数计数
uchar b;//秒计数
TR1 = ;//启动T1
TMOD = 0x10;//T1为定时器,工作模式1 16位计数器
//在初值基础上加,溢出则定时时间到
//晶振是11.0592MHz 65535-(50 000/1.085)==0x4BFC
TH1 = 0x4b;
TL1 = 0xfc;//0x4bfc 定时50ms
while()
{
if(TF1 == )//判断T1是否溢出
{
TH1 = 0x4b;
TL1 = 0xfc;//0x4bfc 定时50ms
TF1 = ;//清零便于下次判断
a++;//50毫秒计数加1
}
if(a == )//判断是否到1秒
{
a = ;//清零便于下次记录50ms的次数
b++;//秒加1
}
if(b == )//检查是否到20秒
{
TR1 = ;//时间到关闭定时器1
P1 = 0xfe;//点亮LED1
}

        display(b);//显示秒的值  
    }  

}

定时器0:

/*定时器0,定时模式 工作模式1 16位计数器,
定时20秒后点亮LED2,数码管显示*/
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit we = P2^;
sbit du = P2^;

uchar code leddata[]={

            0x3F,  //"0"  
            0x06,  //"1"  
            0x5B,  //"2"  
            0x4F,  //"3"  
            0x66,  //"4"  
            0x6D,  //"5"  
            0x7D,  //"6"  
            0x07,  //"7"  
            0x7F,  //"8"  
            0x6F,  //"9"  
            0x77,  //"A"  
            0x7C,  //"B"  
            0x39,  //"C"  
            0x5E,  //"D"  
            0x79,  //"E"  
            0x71,  //"F"  
            0x76,  //"H"  
            0x38,  //"L"  
            0x37,  //"n"  
            0x3E,  //"u"  
            0x73,  //"P"  
            0x5C,  //"o"  
            0x40,  //"-"  
            0x00,  //熄灭  
            0x00  //自定义

                     };

void delay(uint z)
{
uint x,y;
for(x = z; x > ; x--)
for(y = ; y > ; y--);
}

void display(uchar i)
{
uchar shi, ge;
shi = i / ;//求模 i除以10取商的整数部分
ge = i % ;//求余 i除以10取余数部分

P0 = 0xff; //清除断码  
we = ;//打开位选  
P0 = 0xfb;//1111 1011 只选通第三位数码管  
we = ;    //关闭位选

du = ;    //打开段选  
P0 = leddata\[shi\];  
du = ;    //关闭段选  
delay();//延时5毫秒

P0 = 0xff;//清除断码  
we = ;    //打开位选  
P0 = 0xf7;//1111 0111  只选通第四位数码管  
we = ;    //关闭位选

du = ;//打开段选  
P0 = leddata\[ge\];  
du = ;    //关闭段选  
delay();//延时5毫秒  

}

void main()
{
uchar a; //50次数计数
uchar b;//秒计数
TR0 = ;//启动T0
TMOD = 0x01;//T0为定时器,工作模式1 16位计数器
TH0 = 0x4b;
TL0 = 0xfc;//0x4bfc 定时50ms
while()
{
if(TF0 == )//判断T0是否溢出
{
TH0 = 0x4b;
TL0 = 0xfc;//0x4bfc 定时50ms
TF0 = ;//清零便于下次判断
a++;//50毫秒计数加1
}
if(a == )//判断是否到1秒
{
a = ;//清零便于下次记录50ms的次数
b++;//秒加1
}
if(b == )//检查是否到20秒
{
TR0 = ;//时间到关闭定时器1
P1 = 0xfd;//点亮LED2
}

        display(b);//显示秒的值  
    }  

}

定时器1做计数器,定时器0定时:

/*定时器1做计数器,工作模式2,使用定时器0让LED1小灯100毫秒闪烁一次,
定时器1记录LED1闪烁次数,并且用数码管实时显示计数数值。*/
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit we = P2^;
sbit du = P2^;
sbit LED1 = P1^;

uchar code leddata[]={

            0x3F,  //"0"  
            0x06,  //"1"  
            0x5B,  //"2"  
            0x4F,  //"3"  
            0x66,  //"4"  
            0x6D,  //"5"  
            0x7D,  //"6"  
            0x07,  //"7"  
            0x7F,  //"8"  
            0x6F,  //"9"  
            0x77,  //"A"  
            0x7C,  //"B"  
            0x39,  //"C"  
            0x5E,  //"D"  
            0x79,  //"E"  
            0x71,  //"F"  
            0x76,  //"H"  
            0x38,  //"L"  
            0x37,  //"n"  
            0x3E,  //"u"  
            0x73,  //"P"  
            0x5C,  //"o"  
            0x40,  //"-"  
            0x00,  //熄灭  
            0x00  //自定义

                     };

void delay(uint z)
{
uint x,y;
for(x = z; x > ; x--)
for(y = ; y > ; y--);
}

void display(uchar i)
{
uchar bai, shi, ge;
bai = i / ; //显示百位
shi = i % / ; //显示十位
ge = i % ;//显示个位

P0 = 0xff; //清除断码  
we = ;//打开位选  
P0 = 0xfe;//1111 1110  
we = ;    //关闭位选

du = ;    //打开段选  
P0 = leddata\[bai\];  
du = ;    //关闭段选  
delay();//延时5毫秒

P0 = 0xff;//清除断码  
we = ;    //打开位选  
P0 = 0xfd;//1111 1101  
we = ;    //关闭位选

du = ;//打开段选  
P0 = leddata\[shi\];  
du = ;    //关闭段选  
delay();//延时5毫秒

P0 = 0xff;//清除断码  
we = ;    //打开位选  
P0 = 0xfb;//1111 1011  
we = ;    //关闭位选

du = ;//打开段选  
P0 = leddata\[ge\];  
du = ;    //关闭段选  
delay();//延时5毫秒  

}

void main()
{
uchar a; //50次数计数
TR0 = ;//启动T0
TR1 = ;//启动T1
TMOD = 0x61;//T0为定时器,工作模式1 16位计数器,T1为计数器,工作模式2,8位自动重装
TH0 = 0x4b;
TL0 = 0xfc;//0x4bfc 定时50ms
//P3.5来一个脉冲,计数器T1就会自动加1,这里的脉冲应是LED管脚处的脉冲,需要进行串联这两个引脚
TH1 = 0;//8位自动重装,TL1加到255后,会把TH1的0值装载到TL1里面
TL1 = ;//当TL1溢出时自动装入TH1的值
while()
{
if(TF0 == )//判断T0是否溢出
{
TH0 = 0x4b;
TL0 = 0xfc;//0x4bfc 定时50ms
TF0 = ;//清零便于下次判断
a++;//50毫秒计数加1
}
if(a == )//判断是否到100毫秒
{
a = ;//清零便于下次记录50ms的次数
LED1 = ~LED1;//闪烁LED1
}
display(TL1);//显示T1计数值
}
}