MCS-51单片机内部有2个16位的可编程定时/计数器。定时/计数器X(X=0、1)由计数器THX和TLX组成。定时/计数器由特殊寄存器TMOD和TCON决定。

方式寄存器TMOD(TIMER/COUNTER MODE CONTROL REGISTER)

TMOD GATE C/T M1 M0 GATE C/T M1 M0

其中低4位控制定时/计数器0,高4位控制定时/计数器1。

GATE:门控位。当GATE=1时,定时/技术器受外部中断信号INT的控制,当TRX为1时开始计数,为0时停止计数。

C/T(count/timer):当C/T=0时为定时方式,其计数器输入为晶振脉冲的12分频,即对机器周期计数。当C/T=1时为计数方式,计数器的触发输入来自T0或T1的外部脉冲。

M1和M0:操作方式选择位。

M1M0 操作方式 功能
00 方式1 13位计数器(TLX的高3位不使用)
01 方式2 16位计数器
10 方式3 可自动再装载的8位计数器
11 方式4

定时/计数器0分为两个独立计数器

定时/计数器1为串行口波特率发生器

启/停控制寄存器TCON(TIMER CONTROL):

TCON TF1 TR1 TF0 TR0 TE1 IT1 IE0 IT0

TF(timer full):定时器溢出标志

TR(timer running):定时器运行控制位 

后面四位是和中断有关的,前面的博客已经提过了。

定时/计数器的初始化:

1.对方式寄存器TMOD赋值,确定工作方式。

2.预置定时或计数初值,直接将初值写入TL0,TH0或TL1,TH1中。

3.根据需要对中断允许寄存器有关位赋值,以开放或禁止定时/计数器。

4.启动定时/计数器。

 初始值的计算:

计数方式:X = M-计数值

定时器方式: X = M-定时器/T

 

/*  若单片机晶振为12MHz,用定时/计数器0编程实现从P1.0输出周期为500us的方波*/
//  选择定时/计数器0以方式2进行工作
#include<reg51.h>
sbit P1_0 = P1^0;
void mian(){
    TMOD = 0x02;    // 0000 0010   采用方式2
    TH0 = 0x06;     //  2^8-500/2=256-250=6
    TL0 = 0x06;     //  在方式2中,TL定义为加1计数器,TH定义为赋初值寄存器
    TR0 = 1;        //  启动计数/定时器0
    for( ; ; ){
        if(TF0){   //定时器打开后它直接就会跑了,当到了最大值,TF=1
            TF0 = 0;    
            P1_0 = !P1_0;
        }
    }
}

//采用中断的方式
#include<reg51.h>
sbit P1_0 = p1^0;
void main(){
    //时钟初始化
    TMOD = 0x02; 
    TH0 = 0x06;    
    TL0 = 0x06;
    TR0 = 1;
    //中断初始化
    EA = 1;   //打开中断的总允许
    ET0 = 1;  //打开定时器0的中断允许   
    while(1);
}
//中断函数不用我们在主函数中调用,自己时间到了将会运行
void time0_fun(void) interrupt 1 using 0{ //T0的中断号是1 P1_0 = !P1_0; }

 如果定时的时间小于8192us,可以用方式0。小于65536us,可以用方式1。但是方式0和1要在定时时间到后重新定时。

/*  实现周期为1s的方波输出*/
/*采用全局变量作软件计数,计算并判断中断次数实现  */
#include<reg51.h>
sbit P1_1 = P1^1;
unsigned char i;
void main(){
    //时钟初始化
    TMOD = 0x01;
    TH0 = (65536-10000)/256;      //  1000ms/2/50=10ms=10000us
    TL0 = (65536-10000)%256;      //这样赋初值是因为TH0,TL0是八个字节的,不满256的给低位,高于256的给高位
    //65536-10000=55536=1101100011110000B=D8F0H
    //中断初始化
    EA = 1;
    ET0 = 1;
    TR0 = 1;
    i=0;
    while(1);
}
void time0_fun(void) interrupt 1{
    TH0 = (65536-10000)/256;
    TL0 = (65536-10000)%256;
    i++;
    if(i==50){
        P1_1 = !P1_1;
        i = 0;
    }
}
/* 采用定时/计数器1对定时/计数器0的定时时间进行计数实现  */
#include<reg51.h>
sbit P1_1 = P1^1;
sbit P3_5 = P3^5;   // T1的引脚
void main(){
    //时钟的初始化
    TMOD = 0x61;    //0110 001B   T1为计数方式,以方式2工作  T0为定时方式,以方式0工作
    TH0 = 0xD8;     //与上面一样
    TL0 = 0xf0;     //T0每10ms就对T1进行一次变反,这样T1端有一个周期为20ms的周期输出
    TH1 = 0xE7;      //赋初值计数器   256-25 = 231 = 11100111B       25*20 = 500ms
    TL1 = 0xE7;      //加一计数器
    //中断的初始化
    EA = 1;
    ET0 = 1;  ET1 = 1;
    TR0 = 1;  TR1 = 1;
    while(1);
}
void time0_fun(void) interrupt 1{  
    TH0 = 0xD8;
    TL0 = 0xf0;
    P3_5 = !P3^5;
}
void time1_fun(void) interrupt 3{
    P1_1 = !P1_1;
}

 

版权声明:本文为1212dd原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/1212dd/p/13754602.html