专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

89C51单片机定时/计数器0

作者:huqin   来源:本站原创   点击数:  更新时间:2014年05月01日   【字体:

89C51单片机的定时计数功能由特殊功能寄存器TMOD和TCON共同控制。
TMOD没有位地址,不能进行位操作,其每位的名称和功能如下:
TMOD:GATE C/T1  M1 M0 GATE  C/T1   M1  M0
                         D7          D6           D5    D4       D3          D2         D1      D0
 GATE      
C/T1      M1     M0    控制定时计时器1;
 
GATE       C/T0      M1     M0   控制定时计时器0;
GATE=0时,定时计数信号是T0脚状态(P3.4)或机器周期(C/T=0计机器周期,即定时,C/T=1,计T0脚的状态,即计数),计数开始开关是TR0(0关闭计数,1开始计数)。
GATE=1时,定时计数功能由T0脚(P3.4)或者机器周期确定(C/T=0计数机器周期,即定时,C/T=1,计数T0脚的变化状态,即计数),计数开始开关由TR0(0关闭计数,1开始计数)和INT0(管脚P3.2共同确定。
 M1M0是计数方式选择:计数在TH0和TL0进行。
 00为方式0,13位(TH0的8位和TL0的低5位)二进制计数器,由0可数到2的13次方-1;
 01为方式1,16位二进制计数器,由0可数到2的16次方-1;
 10为方式2,8位二进制计数器,TH0放计数初值,计数在TL0进行,溢出后自动将 
                     TH0中的初值装入TL0;
11为方式3,TH0是个8为计数器,HL0是个8位计数器。两个计数器相互独立。
T1和T0功能相同。
特殊功能寄存器TCON,可以位操作,但一般不用位地址,而用位的功能名称:
位地址:8FH  8EH  8DH  8Ch  8Bh  8Ah  89H  88H
TCON :TF1  TR1  TF0   TR0   IE1   IT1   IE0   IT0 

               D7    D6    D5    D4    D3   D2   D1    D0 
TF0是T0计数标志位:定时计数溢出时,该位被自动置1,中断计数结束后自动清0.
TR0是计数开关,GATE=0时,TR0=1打开计数,0关闭。当GATE=1时,和INT0一起控制计数器打开,即GATE=1,TR0=1,INT0=1才可打开计数,否则关闭。
定时/计数时,由TH0 TL0的值开始加1计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式,中断请求由硬件给TF0置1,计数结束后,也就是中断结束后,自动将TF0清0。
/***************定时器定时50ms,在计数20下为1秒,显示60秒计时(查询模式)***********/
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int

int yu[]={
               0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
             };
int t,k,dat;
void delay(int ms)
{
 while(ms--)
   {
    int i;
    for(i=0;i<30;i++);
   }
}
void Timer0()
   {       
     if(TF0==1)//查询TF0为1,说明计数满了,计数结束。
         {
          t++;
          TH0=0x3c;//这里是计数满后重新装入计数初值.也可TH0=(65536-5000)/256
          TL0=0xb0;//计数溢出后再次计数从这里开始,
也可TL0=(65536-5000)%256
       /*如果先计算初值麻烦,还可以用16位二进制的最大值65536-定时计数次数赋值给TH0和TL0,例如定时40ms,需对机器周期计数4000下,可以
            TH0=(65536-4000)/256;TL0=(65536-4000)%*/

          TF0=0;
         }
            //清除溢出标志
   }
void T1s()
{
  if(t==20)//计数一次50ms,20次为1秒
      {t=0;
       dat++;
       if(dat==60)//60次为1分钟
        dat=0;
      }
}
void main()
{
  TMOD=0x01;
   /*此设置(0000 0101)T0的GATE=0,C/T为0,M1M0为01。
    GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
    C/T=0,定时功能,计数机器周期的个数。
    M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满
    再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中
    断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.
    打开计数器0中断将ET0=1,EA=1 */
  TH0=0x3c;//设置计数器计数初值50ms从3CB0H开始计数
  TL0=0xb0;//第一次从这里的设置开始计数
  TR0=1; 
  while(1)
   { 
      Timer0();
      T1s();     
     P0=yu[dat%10];
      delay(1);
      P2=0x01;   
      delay(1);
      P2=0x00;
     P0=yu[dat/10];
      delay(1);
      P2=0x02;
      delay(1);
      P2=0x00;   
   }

/*******定时/计数器0中断应用,按键没按一次数码管显示加1(中断模式)*************/
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
int yu[]={
               0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
             };
int k;
void delay(int ms)
{
 while(ms--)
   {
    int i;
    for(i=0;i<30;i++);
   }
}
void ddd() interrupt 1
   {
     TH0=0xff;//这里是计数满后重新装入计数初值
     TL0=0xfa;//计数溢出后再次计数从这里开始
     delay(5);
     if(TF0==0)//计数中断时TF0由硬件置1,响应中断并开始计数,计数产生溢出后自动清0,结束计数。
            {        //所以,响应中断后,查询TF0的状态可以判断中断计数是否结束
               if(k==99)
               k=0;
              else
               k++;
           }        
   }
void main()
{
  TMOD=0x05;
/*此设置(0000 0101)T0的GATE=0,C/T为1,M1M0为01。
   GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
    C/T=1,计数功能,计数管脚T0(P3.4)的状态变化。
   M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.打开计数器0中断将ET0=1,EA=1 */

  TH0=0xff;//设置计数器计数初值
  TL0=0xfc;//第一次从这里的设置开始计数
  ET0=1;

  TR0=1;
  EA=1;
  while(1)
   {
   P0=yu[k%10];
      delay(1);
      P2=0x01;   
      delay(1);
      P2=0x00;
      P0=yu[k/10];
      delay(1);
      P2=0x02;
      delay(1);
      P2=0x00;   
   }
}



/******用查询模式计数
#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
int yu[]={
               0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f
             };
int k;
void delay(int ms)
{
 while(ms--)
   {
    int i;
    for(i=0;i<30;i++);
   }
}
void jishu()
   {     
     if(TF0==1)//查询TF0,为1,说明计数满了,计数结束。
         {
           TH0=0xff;//这里是计数满后重新装入计数初值
           TL0=0xff;//计数溢出后再次计数从这里开始
           delay(5);
           if(k==99)
           k=0;
           else
           k++;
         }
        TF0=0;     //清除溢出标志
   }
void main()
{
  TMOD=0x05;
/*此设置(0000 0101)T0的GATE=0,C/T为1,M1M0为01。
   GATE=0,关闭INT0(P3.2)脚对计数开始的控制,只由TR0控制开始。
    C/T=1,计数功能,计数管脚T0(P3.4)的状态变化。
   M1M0=01,计数方式选择方式1,16位二进制计数器,由TH0 TL0开始计数到FFFFH满,再计数就溢出,如果是定时/计数模式,溢出后将TF0置1,计数定时结束,如果是中断模式清0,有硬件给TF0置1,计数结束,也就是中断结束,自动将TF0清0.打开计数器0中断将ET0=1,EA=1 */

  TH0=0xff;//设置计数器计数初值
  TL0=0xff;//第一次从这里的设置开始计数
  TR0=1;
  while(1)
   { 
      jishu();
   P0=yu[k%10];
      delay(1);
      P2=0x01;   
      delay(1);
      P2=0x00;
     P0=yu[k/10];
      delay(1);
      P2=0x02;
      delay(1);
      P2=0x00;   
   }
}
关闭窗口

相关文章