zoukankan      html  css  js  c++  java
  • MCU 51-3定时器

    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只适用于定时器0。如果使定时器1为工作方式3,则定时器1将处于关闭状态。 

    当T0为工作方式3时,TH0和TL0分成2个独立的8位计数器。其中,TL0既可用作定时器,又可用作计数器,并使用原T0的所有控制位及其定时器回零标志和中断源。TH0只能用作定时器,并使用T1的控制位TRl、回零标志TFl和中断源。 
    通常情况下,T0不运行于工作方式3,只有在T1处于工作方式2,并不要求中断的条件下才可能使用。这时,T1往往用作串行口波特率发生器,TH0用作定时器,TL0作为定时器或计数器。所以,方式3是为了使单片机有1个独立的定时器/计数器、1个定时器以及1个串行口波特率发生器的应用场合而特地提供的。这时,可把定时器l用于工作方式2,把定时器0用于工作方式3。

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

    定时器1:

    /*定时器1,定时模式 工作模式1 16位计数器,
    定时20秒后点亮LED1,数码管显示*/
    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint  unsigned int
    sbit we = P2^7;
    sbit du = P2^6;
    
    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 > 0; x--)
            for(y = 114; y > 0 ; y--);
    }
    
    void display(uchar i)
    {
        uchar shi, ge;
        shi = i / 10;//求模  i除以10取商的整数部分
        ge  = i % 10;//求余  i除以10取余数部分
    
        P0 = 0xff; //清除断码
        we = 1;//打开位选
        P0 = 0xfe;//1111 1110 只选通第一位数码管
        we = 0;    //关闭位选
    
        du = 1;    //打开段选
        P0 = leddata[shi];
        du = 0;    //关闭段选
        delay(5);//延时5毫秒
        
        P0 = 0xff;//清除断码
        we = 1;    //打开位选
        P0 = 0xfd;//1111 1101  只选通第二位数码管
        we = 0;    //关闭位选
        
        du = 1;//打开段选
        P0 = leddata[ge]; 
        du = 0;    //关闭段选
        delay(5);//延时5毫秒    
    }
    
    void main()
    {
            uchar a; //50次数计数
            uchar b;//秒计数
            TR1 = 1;//启动T1
            TMOD = 0x10;//T1为定时器,工作模式1 16位计数器
    //在初值基础上加,溢出则定时时间到
    //晶振是11.0592MHz 65535-(50 000/1.085)==0x4BFC
    TH1 = 0x4b; TL1 = 0xfc;//0x4bfc 定时50ms while(1) { if(TF1 == 1)//判断T1是否溢出 { TH1 = 0x4b; TL1 = 0xfc;//0x4bfc 定时50ms TF1 = 0;//清零便于下次判断 a++;//50毫秒计数加1 } if(a == 20)//判断是否到1秒 { a = 0;//清零便于下次记录50ms的次数 b++;//秒加1 } if(b == 20)//检查是否到20秒 { TR1 = 0;//时间到关闭定时器1 P1 = 0xfe;//点亮LED1 } display(b);//显示秒的值 } }

     定时器0:

    /*定时器0,定时模式 工作模式1 16位计数器,
    定时20秒后点亮LED2,数码管显示*/
    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint  unsigned int
    sbit we = P2^7;
    sbit du = P2^6;
    
    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 > 0; x--)
            for(y = 114; y > 0 ; y--);
    }
    
    void display(uchar i)
    {
        uchar shi, ge;
        shi = i / 10;//求模  i除以10取商的整数部分
        ge  = i % 10;//求余  i除以10取余数部分
    
        P0 = 0xff; //清除断码
        we = 1;//打开位选
        P0 = 0xfb;//1111 1011 只选通第三位数码管
        we = 0;    //关闭位选
    
        du = 1;    //打开段选
        P0 = leddata[shi];
        du = 0;    //关闭段选
        delay(5);//延时5毫秒
        
        P0 = 0xff;//清除断码
        we = 1;    //打开位选
        P0 = 0xf7;//1111 0111  只选通第四位数码管
        we = 0;    //关闭位选
        
        du = 1;//打开段选
        P0 = leddata[ge]; 
        du = 0;    //关闭段选
        delay(5);//延时5毫秒    
    }
    
    void main()
    {
            uchar a; //50次数计数
            uchar b;//秒计数
            TR0 = 1;//启动T0
            TMOD = 0x01;//T0为定时器,工作模式1 16位计数器
            TH0 = 0x4b;
            TL0 = 0xfc;//0x4bfc    定时50ms                
            while(1)
            {
                if(TF0 == 1)//判断T0是否溢出
                {
                    TH0 = 0x4b;
                    TL0 = 0xfc;//0x4bfc    定时50ms
                    TF0 = 0;//清零便于下次判断
                    a++;//50毫秒计数加1    
                }
                if(a == 20)//判断是否到1秒
                {
                    a = 0;//清零便于下次记录50ms的次数
                    b++;//秒加1
                }
                if(b == 20)//检查是否到20秒
                {
                    TR0 = 0;//时间到关闭定时器1
                    P1 = 0xfd;//点亮LED2
                }
    
                display(b);//显示秒的值
            }
    }

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

    /*定时器1做计数器,工作模式2,使用定时器0让LED1小灯100毫秒闪烁一次,
    定时器1记录LED1闪烁次数,并且用数码管实时显示计数数值。*/
    #include <reg52.h>
    #include <intrins.h>
    #define uchar unsigned char
    #define uint  unsigned int
    sbit we = P2^7;
    sbit du = P2^6;
    sbit LED1 = P1^0;
    
    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 > 0; x--)
            for(y = 114; y > 0 ; y--);
    }
    
    void display(uchar i)
    {
        uchar bai, shi, ge;
        bai = i / 100; //显示百位
        shi = i % 100 / 10;    //显示十位
        ge  = i % 10;//显示个位
    
        P0 = 0xff; //清除断码
        we = 1;//打开位选
        P0 = 0xfe;//1111 1110 
        we = 0;    //关闭位选
    
        du = 1;    //打开段选
        P0 = leddata[bai];
        du = 0;    //关闭段选
        delay(5);//延时5毫秒
        
        P0 = 0xff;//清除断码
        we = 1;    //打开位选
        P0 = 0xfd;//1111 1101  
        we = 0;    //关闭位选
        
        du = 1;//打开段选
        P0 = leddata[shi]; 
        du = 0;    //关闭段选
        delay(5);//延时5毫秒
        
        P0 = 0xff;//清除断码
        we = 1;    //打开位选
        P0 = 0xfb;//1111 1011  
        we = 0;    //关闭位选
        
        du = 1;//打开段选
        P0 = leddata[ge]; 
        du = 0;    //关闭段选
        delay(5);//延时5毫秒    
    }
    
    void main()
    {
            uchar a; //50次数计数
            TR0 = 1;//启动T0
            TR1 = 1;//启动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 = 0;//当TL1溢出时自动装入TH1的值 while(1) { if(TF0 == 1)//判断T0是否溢出 { TH0 = 0x4b; TL0 = 0xfc;//0x4bfc 定时50ms TF0 = 0;//清零便于下次判断 a++;//50毫秒计数加1 } if(a == 2)//判断是否到100毫秒 { a = 0;//清零便于下次记录50ms的次数 LED1 = ~LED1;//闪烁LED1 } display(TL1);//显示T1计数值 } }
    
    
    /*利用定时器0工作模式0,编写间隔一秒闪烁灯程序*/
    # include <reg52.h>
    sbit D1 = P1^0;//LED灯对于IO口位声明
    
    void main()
    {
    //晶振11.0592MHz 8192-(5000/1.085) TMOD
    = 0x00; //定时器0工作模式0,13位计数器 TH0 = (8192 - 4608) / 32;//TH储存13位中高8位 TL0 = (8192 - 4608) % 32;//TL储存13位中低5位,定时5毫秒 ET0 = 1; //开定时器0中断 TR0 = 1; //启动定时器0 EA = 1; //开总中断 while (1);//等待中断 } void Timer0() interrupt 1//定时器0中断服务程序 { static unsigned char i;//溢出次数计数静态变量 TH0 = (8192 - 4608) / 32; TL0 = (8192 - 4608) % 32;/*每次溢出后需给定时器0放置初值*/ i++; if (i == 200) //200次溢出后1秒时间到 { D1 = ~D1;//将LED灯状态取反 i = 0; // 清零溢出计次数 } }
    /*晶振平率11.0592Mhz利用定时器0工作模式1,编写间隔一秒闪烁灯程序*/
    # include <reg52.h>
    sbit D1 = P1^0;//LED灯对应IO口位声明
    void main()
    {
        TMOD = 0x01;//设置定时器0的工作方式1 
        TH0    = 0x4c;//寄存器TH0中装入4C,或者该语句改为TH0 = (65536 - 46080) /256
        TL0 = 0x00;//寄存器TL0中装入00,或者该语句改为TL0 = (65536 - 46080) % 256
        ET0 = 1; //开定时器T0中断    
        EA  = 1; //开总中断,上一句和此句可以合并为一句IE=0x82H
        TR0 = 1; //启动定时器0
        while (1);//等待中断    
    }
    void Timer0() interrupt 1//定时器T0中断服务程序
    {
        static unsigned char i;//静态计数变量
        TH0    = 0xDC;
        TL0 = 0x00;/*每次加1计数器计满溢出后,需给加1计数器重新装入初值*/
        i++;
        if (i == 20) //循环次数达到20次,1秒定时时间到
        {
            D1 = !D1;//将LED灯状态取反
            i = 0;//清零计数变量
        }
    }
    /*晶振频率12Mhz利用定时器0工作模式2,编写间隔500毫秒闪烁灯程序*/
    # include <reg52.h>
    sbit D1 = P1^0;//LED灯对于IO口位声明
    
    void main()
    {
        TMOD = 0x02;    //定时器0工作模式2,自动重装8位计数器
        TH0    = 256 - 200;//TH储存8位重装初值
        TL0 = 256 - 200;//TL储存8位初值,定时200微秒 
        ET0 = 1; //开定时器0中断
        TR0 = 1; //启动定时器0
        EA  = 1; //开总中断
        while (1);//等待中断    
    }
    
    void Timer0() interrupt 1//定时器0中断服务程序
    {
        static unsigned int i;//溢出次数计数静态变量
        i++;
        if (i == 2500) //2500次溢出后500毫秒时间到
        {
            D1 = ~D1;//将LED灯状态取反
            i = 0;     //    清零溢出计次数
        }
    }
    当T0为工作方式3时,TH0和TL0分成2个独立的8位计数器。
    其中,TL0既可用作定时器,又可用作计数器,
    并使用原T0的所有控制位及其定时器回零标志和中断源。
    TH0只能用作定时器,并使用T1的控制位TRl、回零标志TFl和中断源。 

    /*
    晶振频率12Mhz利用定时器0工作模式3 编写利用TL0计数器所对应的定时器实现间隔500毫秒闪烁一个LED灯 利用TH0计数器所对应的定时器实现间隔250毫秒闪烁另一个LED灯 */ # include <reg52.h> sbit D1 = P1^0;//LED灯对于IO口位声明 sbit D2 = P1^1; void main() { TMOD = 0x03; //定时器0工作模式3,2个独立的8位计数器 TH0 = 256 - 200;//TH0储存8位初值, 定时200微秒 TL0 = 256 - 200;//TL0储存8位初值,定时200微秒 ET0 = 1; //开定时器TL0中断 ET1 = 1; //开定时器TH0中断 TR0 = 1; //启动定时器TL0 TR1 = 1; //启动定时器TH0 EA = 1; //开总中断 while (1);//等待中断 } void TL0_Timer() interrupt 1//定时器TL0中断服务程序 { static unsigned int i;//溢出次数计数静态变量 TL0 = 256 - 200;//TL0初值重装,定时200微秒 i++; if (i == 2500) //2500次溢出后500毫秒时间到 { D1 = ~D1;//将第一个LED灯状态取反 i = 0; // 清零溢出计次数 } } void TH0_Timer() interrupt 3//定时器TH0中断服务程序 { static unsigned int i;//溢出次数计数静态变量 TH0 = 256 - 200;//TH0初值重装,定时200微秒 i++; if (i == 1250) //1250次溢出后250毫秒时间到 { D2 = ~D2;//将第二个LED灯状态取反 i = 0; // 清零溢出计次数 } }
    /*
    编写利用定时器0工作模式2,8位计数模式,用杜邦线一端接P1.1
    另一端P3.4引脚,记录P1.1脉冲次数,每10次脉冲触发一次中断,
    使计数器溢出产生中断点亮LED小灯*/
    # include <reg52.h>
    sbit D1 = P1^0;//LED灯对于IO口位声明
    sbit IN = P1^1;//脉冲输出IO口
    
    void main()
    {
        unsigned int  b;//延时变量
        TMOD = 0x06;    //定时器0工作模式2,8位计数模式(00000110)
        TH0    = 256 - 10;    //TH储存8位重装初值
        TL0 = 256 - 10;    //TL储存8位初值
        ET0 = 1; //开定时器0中断
        TR0 = 1; //启动定时器0
        EA  = 1; //开总中断
        while (1)
        {
            IN = 1;//置高脉冲输出IO口
            for(b = 0; b < 60000 ; b++); //延时
            IN = 0;//置低脉冲输出IO口
            for(b = 0; b < 60000 ; b++);//延时        
        }
    }
    
    void Timer0() interrupt 1//定时器0中断服务程序
    {
        D1 = ~D1;//将LED灯状态取反
    }
  • 相关阅读:
    Linux 6.2 配置NTP服务
    配置SSH三大框架报错
    Linux 6.2 源码安装和配置Puppet
    PGA 内存管理
    调整linux系统时间和时区与Internet时间同步
    Java 文件分块上传客户端和服务器端源代码
    Java 文件分块上传服务器端源代码
    Java 服务器端支持断点续传的源代码【支持快车、迅雷】(仅支持 HTTP 协议)
    bbed使用
    OracleDatabase 11g安装bbed
  • 原文地址:https://www.cnblogs.com/darren-pty/p/13283335.html
Copyright © 2011-2022 走看看