微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 51单片机定时器不准,请各位高手进来看看。。。。

51单片机定时器不准,请各位高手进来看看。。。。

时间:10-02 整理:3721RD 点击:

#include<reg51.h>
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit key=P1^7;
bit flag=0;
uint t;
uchar sec=0,min=0,hour=0,x=0,u=0xfe,tt=0;//t计时一秒 tt计时2毫秒
uchar code Num[]=
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0xff;
};
uchar Num_Buf[]=
{0,0,10,0,0,10,0,0};

void display()
{
   if(tt==1)
  {
    tt=0;
    P2=u;
    u=_crol_(u,1);
    P0=Num[Num_Buf[x]];
    x++;
    if(x==8)x=0;
  }
}
void timer0()interrupt 1
{
ET0=0;
TH0=-(2010/256);
TL0=-(2010%256);
t++;
tt++;
if(t==500)
{
t=0;
sec++;
}
ET0=1;
}

void main()
{
EA=1;
ET0=1;
TR0=1;
TMOD=0x01;
TH0=-(2000/256);
TL0=-(2000%256);
P2=0xff;
P0=0xff;
while(1)
{
   display();
    if(sec==60)
    {
          sec=0;
          min++;
          if(min==60)
          {
               min=0;
               hour++;
               if(hour==24)
               {
               hour=0;
                }
           }
    }
  Num_Buf[6]=sec/10;
  Num_Buf[7]=sec%10;
  Num_Buf[3]=min/10;
  Num_Buf[4]=min%10;
  Num_Buf[0]=hour/10;
  Num_Buf[1]=hour%10;
}
}


我是一个新手,才学51单片机。
这是我编的一个单纯的计时器,没有其他功能, 只有从00-00-00开始。后来发现,定时时间不准,定时器初值越小的时候越不准,误差很大。定时器初值补偿也试过,无法修正。请各位高手帮我看看哪里有问题。晶振是12兆的。
无论怎样,先说声谢谢大家。

定时器做的时钟不准很正常,要想精确用时钟芯片,如:DS1302

用单片机的晶体振荡器,程序定时会有误差。

试试这样修改下:
/*****************************************************************************************
                                                           修改版
*****************************************************************************************/
#include<reg51.h>
#include<intrins.h>
typedef unsigned char uchar;
typedef unsigned int uint;
sbit key=P1^7;
bit flag=0;
uint t;
uchar sec=0,min=0,hour=0,x=0,u=0xfe,tt=0;//t计时一秒 tt计时2毫秒
uchar code Num[]=
{
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0xff;
};
uchar Num_Buf[]=
{0,0,10,0,0,10,0,0};
void display()
{
   if(tt==1)
  {
    tt=0;
    P2=u;
    u=_crol_(u,1);
    P0=Num[Num_Buf[x]];
    x++;
    if(x==8)x=0;
  }
}
void timer0()interrupt 1
{
ET0=0;
//TH0=-(2010/256);
//TL0=-(2010%256);
//定时周期尽量设置长一些,因为进入中断以及重装初值都需要消耗时间。这个时间和你定时周期越接近,定时越不精确。
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
t++;
tt++;
//if(t==500)
if(t==20)
{
t=0;
sec++;
  if(sec==60)
    {
          sec=0;
          min++;
          if(min==60)
          {
               min=0;
               hour++;
               if(hour==24)
               {
               hour=0;
                }
           }
    }
}
ET0=1;
}

void main()
{
EA=1;
ET0=1;
TR0=1;
TMOD=0x01;
//TH0=-(2000/256);
//TL0=-(2000%256);
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
P2=0xff;
P0=0xff;
while(1)
{
   display();
//这里潜在的问题,假如此时sec=60,主函数将要执行 if(sec==60)的时候,突然发生定时器中断,
//在中断里面进行了src++,中断退出后,返回主函数继续执行 if(sec==60),而此时sec已经变成了61,
//这里的判断是不是就失效呢?
//在程序中要避免在中断和主函数同时使用一个资源,(资源:变量,函数,硬件等待)
//否则就会因为资源争夺而发生冲突。
/* if(sec==60)
    {
          sec=0;
          min++;
          if(min==60)
          {
               min=0;
               hour++;
               if(hour==24)
               {
               hour=0;
                }
           }
    }*/
  Num_Buf[6]=sec/10;
  Num_Buf[7]=sec%10;
  Num_Buf[3]=min/10;
  Num_Buf[4]=min%10;
  Num_Buf[0]=hour/10;
  Num_Buf[1]=hour%10;
}
}

楼上分析得很到位

晶体震荡器会有误差     这是不可避免的    如果要即时准的用ds12c887吧1302也行

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top