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

时间:2024-02-18 17:34:23

 

  

 

定时器/计数器

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

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

定时器 也是对脉冲进行计数完成的,计数的是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;
}
外中断