• Keil C51学习 5 定时器/计数器


     

      

    定时器/计数器

    应用场合:定时或延时控制、对外部事件的检测、计数等。

    计数器 就是对外部输入脉冲的计数;

    定时器 也是对脉冲进行计数完成的,计数的是MCS-51内部产生的标准脉冲,通过计数脉冲个数实现定时。

    T0  P3.4

    T1  P3.5

    T2  P1.0

    每个定时器内部结构实际上就是一个可编程的加法器,由编程来设置它工作在定时状态还是计数状态。

    单片机复位,定时器数据清零。

    定时器/计数器组成: 两个16位定时器T0T1,以及他们的工作方式寄存器TMOD控制寄存器TCON等组成。

    定时器T0T1各由两个8位特殊功能寄存器TH0、TL0、TH1、TH1构成。

    TH0(8位)、TL0(8位) =》16位的定时计数器 T0

    TH1(8位)、TL1 (8位)=》16位的定时计数器 T1

    TH0和TL0:存放定时器T0的初值或计数结果;TH0存放高8位,TL0存放低8位

    TH1和TL1:存放定时器T1的初值或计数结果;TH·存放高8位,TL·存放低8位

    TMOD:用于设置定时器的工作模式和工作方式;工作方式4种(0、1、2、3)

    TCON:用于启动和停止定时器的计数,并控制定时器的状态。

    TMOD

    M1 M0——工作方式选择位

    M1   M0
    
    0  0  方式0,13位定时器/计数器(TH0用低5位,TL0用8位)
    0  1  方式1,16定时器/计数器  (TH0用8位,TL0用8位;每次溢出TH0,TL0都会置零)
    1  0  方式2,8位常数自动重新装载
    1  1  方式3,仅适用于T0,T0分为两个8位;T1停止计数

    TCON

    特殊功能寄存器TCON高4位定时器的运行控制位和溢出标志位,低4位为外部中断的触发方式控制位和锁存外部中断请求源。

    TCON格式如下:

    D7    D6      D5      D4       D3      D2      D1     D0
    
    TF1    TR1     TF0     TR0     IE1     IT1     IE0     IT0

    高四位功能:

    (1)TF1、TF0 计数溢出标志位

    (2)TR1、TR0 计数支行控制位

      TRX=1: 启动定时器/计数器工作

      TRX=0: 停止定时器/计数器工作

    低四位功能:(外部中断)

      IE1:外部中断1请求标志位,当外部中断1被触发时置1。
      IT1:外部中断1触发方式选择位。当IT1=0,为低电平触发方式;当IT1=1,为下降沿触发方式。
      IE0:外部中断0请求标志位,当外部中断0被触发时置1。
      IT0:外部中断0触发方式选择位。 当IT0=0,为低电平触发方式;当IT0=1,为下降沿触发方式。

    工作原理

    1、通过设置TMOD、TCON 设置定时计数器的工作方式以及工作模式

    2、设置定时计数器T0和T1这两个定时计数器寄存器的一个初值

    每个机器周期到来时:T0++;当TL0=0xff,TH0++

              当TH0=0xff,并且TL0=0xff,称作溢出中断(255*255=65535) 

    初值=T0溢出值-计数次数

    指令周期=机器周期X2

    TH0=(定时计数器的初值)/256;

    TL0=(定时计数器的初值)%256;

    定时器设置

    (1)  设置TMOD  TMOD=0X01;

    (2) 计算出初值

    (3)  开放总中断  EA=1;

    (4) 启动定时计数器 TR0(1)=1;

    (5) 设置中断程序

    void fun(void) interrupt 1  —— 定时计数器0溢出中断服务程序

    void timer0(void) interrupt 1 using 1 
    { 
    …………… 
    }
    timer0 是函数名,可以任意取,但是不要和关键字重复。
    interrupt 1 是非常重要的,interrupt 是关键字,表示中断,1 表示 1 号中断即定时器 0 中断。
     
    中断号 0~4,分别表示外部中断 0→定时器 0→外部中断 1→定时器 1→串口中断。
     
    using 1 表示使用第 1 组寄存器,51 单片机中一共有 4 组寄存器,每组寄存器是 R0~R7。
     
     使用模式1
    #include <STC89C51RC.H>
    typedef unsigned char u8;
    typedef unsigned int u16;
     u16 timer;
    sbit led=P1^0;
    void Init_timer0(void)
    {
     TMOD = 0x01;      //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响             
     TH0=(65535-50000)/256;          //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
     TL0=(65535-50000)%256;
     EA=1;            //总中断打开
     ET0=1;           //定时器中断打开
     TR0=1;           //定时器开关打开
    }
     void main (void)
     {
         Init_timer0();
       while (1)         //主循环
       {                  //主循环中添加其他需要一直工作的程序      
    //    delay(100);//执行100次
       }
     }
     void timer0_Service(void) interrupt 1
     {
         TH0=(65535-50000)/256; //重新设置初值
         TL0=(65535-50000)%256;
         timer++;
            if(timer==20)
            {
                timer=0;
                led=~led;
            }
     }
    使用模式1

    定时器1

    /*-----------------------------------------------
      名称:定时器1
      论坛:www.doflye.net
      编写:shifang
      日期:2009.5
      修改:无
      内容:通过定时让LED灯闪烁
    ------------------------------------------------*/
    #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    
    sbit LED=P1^0;    //定义LED端口
    
    /*------------------------------------------------
                        定时器初始化子程序
    ------------------------------------------------*/
    void Init_Timer1(void)
    {
     TMOD |= 0x10;      //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响 
     TH1=0x00;          //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
     TL1=0x00;
     EA=1;            //总中断打开
     ET1=1;           //定时器中断打开
     TR1=1;           //定时器开关打开
    }
    /*------------------------------------------------
                        主程序
    ------------------------------------------------*/
    main()
    {
     Init_Timer1();
     while(1);
    }
    /*------------------------------------------------
                     定时器中断子程序
    ------------------------------------------------*/
    void Timer1_isr(void) interrupt 3 using 1
    {
     TH1=0x00;         //重新赋值
     TL1=0x00;
    
     LED=~LED;       //LED闪烁
    
    }
    定时器1

     定时器2

    /*-----------------------------------------------
      名称:定时器2
      论坛:www.doflye.net
      编写:shifang
      日期:2009.5
      修改:无
      内容:通过定时让LED灯闪烁
    ------------------------------------------------*/
    #include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
    
    sbit LED=P1^0;    //定义LED端口
    
    
    /*------------------------------------------------
                        定时器初始化子程序
    ------------------------------------------------*/
    void TIM2Inital(void)
    {
      RCAP2H = (65536-60000)/256;//晶振12M 60ms 16bit 自动重载
      RCAP2L = (65536-60000)%256;
      ET2=1;                     //打开定时器中断
      EA=1;                      //打开总中断
      TR2=1;                     //打开定时器开关
    }
    /*------------------------------------------------
                        主程序
    ------------------------------------------------*/
    main()
    {
     TIM2Inital();
     while(1);
    }
    
    /*------------------------------------------------
                     定时器中断子程序
    ------------------------------------------------*/
    void TIM2(void) interrupt 5 using 1//定时器2中断
    {
    
        TF2=0;
        LED=~LED;               //指示灯反相
       
    }
    定时器2
       中断加数码管9999计数
    #include "reg52.h"             //此文件中定义了单片机的一些特殊功能寄存器
    #include <absacc.h>             //包含绝对地址访问库函数
    #define SEG1 XBYTE[0xffec]
    #define SEG2 XBYTE[0xffed]
    #define SEG3 XBYTE[0xffee]
    #define SEG4 XBYTE[0xffef]
    typedef unsigned int u16;      //对数据类型进行声明定义
    typedef unsigned char u8;
    
    sbit led=P1^0;     //定义P10口是led
    //共阳
    u8 code smg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 //0-9
    };
    
    /*******************************************************************************
    * 函 数 名         : Timer0Init
    * 函数功能           : 定时器0初始化
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Timer0Init()
    {
        TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
    
        TH0=0XFC;    //给定时器赋初值,定时1ms
        TL0=0X18;    
        ET0=1;//打开定时器0中断允许
        EA=1;//打开总中断
        TR0=1;//打开定时器            
    }
    
    int count;
    /*******************************************************************************
    * 函 数 名       : main
    * 函数功能         : 主函数
    * 输    入       : 无
    * 输    出         : 无
    *******************************************************************************/
    void main()
    {    
        SEG1=SEG2=SEG3=SEG4=0xff;//全灭
        Timer0Init();  //定时器0初始化
        while(1)
        {
                
            SEG4 = smg[count%10];
                SEG3 = smg[count/10%10];    
                SEG2 = smg[count/100%10];
                SEG1 = smg[count/1000%10];
        }        
    }
    
    /*******************************************************************************
    * 函 数 名         : void Timer0() interrupt 1
    * 函数功能           : 定时器0中断函数
    * 输    入         : 无
    * 输    出         : 无
    *******************************************************************************/
    void Timer0() interrupt 1
    {
        static u16 i;
        TH0=0XFC;    //给定时器赋初值,定时1ms
        TL0=0X18;
        i++;
        if(i==2000)
        {
            i=0;
            led=~led;    
            count++;
        }        
    }
    数码管9999计数器

    定时加数码管9999计数

    #include<reg52.h>//包含访问sfr库函数
    #include<intrins.h>//包含访问内联库函数
    #include <absacc.h>  
    typedef unsigned int uint;      //对数据类型进行声明定义
    typedef unsigned char uchar;    
    sbit P10=P1^0;
    sbit k1=P3^2;           //包含绝对地址访问库函数
    #define SEG1 XBYTE[0xffec]
    #define SEG2 XBYTE[0xffed]
    #define SEG3 XBYTE[0xffee]
    #define SEG4 XBYTE[0xffef]
    //共阳
    uchar code smg[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90 };//0-9
    /*
        精确定时1秒闪烁LED
     */
     uint count;
    main()
    {
            RCAP2H=0X10; //赋值52 0X1000,溢出30次等于1秒
            RCAP2L=0X00;
            TR2=1;    //启动定时器
            ET2=1;    //打开定时器0中断
            EA=1;        //打开总中断
         SEG1=SEG2=SEG3=SEG4=0xff;//全灭
        while(1)
        {
             SEG4 = smg[count%10];
         SEG3 = smg[count/10%10];    
         SEG2 = smg[count/100%10];
         SEG1 = smg[count/1000%10];
        }
    }
    
    //定时器2中断
    timer2() interrupt 5    //定时器2中断是5号
    {
        static uchar t;
        TF2=0;
        t++;
        if(t==30)
        {
            t=0;
             count++;
            P10=~P10;
        }
    }
    数码管9999计数

    定时器0

    #include<reg52.h>//包含访问sfr库函数
    sbit P10=P1^0;
    sbit k1=P3^2;
    u16 i;
    main()
    {
            TMOD=0X01;//定时器0,16位工作方式
            TR0=1;    //启动定时器
            ET0=1;    //打开定时器0中断
            EA=1;        //打开总中断
        while(1)
        {
        }
    }
    
    //定时器0中断
    timer0() interrupt 1    //定时器0中断是1号
    {
        TH0=0X00;    //写入定时器0初始值0X0005
        TL0=0X06;
        while(k1);
        P10=~P10;//反转LED灯的状态
    }

     精确定时1秒

    #include<reg52.h>//包含访问sfr库函数
    #include<intrins.h>//包含访问内联库函数
    typedef unsigned int u16;      //对数据类型进行声明定义
    typedef unsigned char uchar;    
    sbit P10=P1^0;
    sbit k1=P3^2;
    /*
        精确定时1秒闪烁LED
     */
    main()
    {
            RCAP2H=0X10; //赋值52 0X1000,溢出30次等于1秒
            RCAP2L=0X00;
            TR2=1;    //启动定时器
            ET2=1;    //打开定时器0中断
            EA=1;        //打开总中断
        while(1)
        {
        }
    }
    
    //定时器2中断
    timer2() interrupt 5    //定时器2中断是5号
    {
        static uchar t;
        TF2=0;
        t++;
        if(t==30)
        {
            t=0;
            P10=~P10;
        }
    }
    定时1秒闪烁

     外中断

    #include<reg52.h>//包含访问sfr库函数
    sbit P10=P1^0;
    sbit K1=P3^2; 
    /*
    外中断的用法。也就是外部 IO 的中断 INT0,和 INT1。
    对应的引脚是 P32 和 P33。
    在我们的电路图中,P32 也就是接在 K1 的引脚。
    所以当我们按下 P32 接到地的时候,可以触发一个 INT0 中断.
    当然,必须预先初始化才会启动。
    */
    main()
    {
            IT0=1;//外中断跳变产生中断
                    EX0=1;
            EA=1;        //打开总中断
        while(1);
    }
     int0() interrupt 0
    {
        P10=~P10;
    }
    外中断
  • 相关阅读:
    [转]nmake命令(windows下的makefile)
    [转]Visual Studio 2010 C++ 工程文件解读
    [转]开源库的编译
    强软弱虚引用试验
    ArtHas JVM在线排查工具
    JVM常用参数
    CMS两个常见问题
    jvisual vm连接
    jconsole连接
    JVM调优
  • 原文地址:https://www.cnblogs.com/bymeet/p/14349684.html
Copyright © 2020-2023  润新知