微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 怎样89c51单片机定时器的精度?

怎样89c51单片机定时器的精度?

时间:10-02 整理:3721RD 点击:
这是我自己按照郭天祥视频第九节的课后作业编的程序,放掉电的计时器。
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
uchar code table[]={0x3f,0x06,0x5b,0x4f,
                    0x66,0x6d,0x7d,0x07,
                                     0x7f,0x6f,0x77,0x7c,
                                              0x39,0x5e,0x79,0x71};    //共阴数码管表
uchar date,sec,save,time0;
sbit sda=P2^0;
sbit scl=P2^1;
sbit dula=P2^6;
sbit wela=P2^7;
void somenop()//小延时
{  ;  ;  }
void delay(uint z)//ms延时
{
   uint x,y;
   for(x=0;x<110;x++)
      for(y=0;y<z;y++);
}
void display(uchar x)//数码管显示
{
        dula=1;
        P0=table[x/10];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xfe;
        wela=0;
        P0=0x00;
        delay(1);
        dula=1;
        P0=table[x%10];
        dula=0;
        P0=0xff;
        wela=1;
        P0=0xfd;
        wela=0;
        P0=0x00;
        delay(1);
}   
void I2Cstart()    //起始信号                              
{       
        sda=1;
        somenop();
        scl=1;
        somenop();
        sda=0;
        somenop();                        
}       
void I2Cstop()      //终止信号                          
{
        sda=0;
        somenop();
        scl=1;
        somenop();
        sda=1;
        somenop();                           
}
void I2Cresponse()        //应答信号                     
{       
        uchar i;
        scl=1;
        somenop();
        while((sda==1)&&(i<250))i++;
        scl=0;
        somenop();                           
}
void write_byte(uchar date)  //写数据
{
        uchar i,j;
        j=date;
        scl=0;
        somenop();
        for(i=0;i<8;i++)
        {
                j=j<<1;
                sda=CY;
                somenop();
                scl=1;
                somenop();
                scl=0;
                somenop();
        }
        sda=1;
        somenop();
}
                                          
uchar read_byte()                //读数据
{
        uchar i,j,k;
        scl=0;
        somenop();
        sda=1;
        somenop();
        for(i=0;i<8;i++)
        {
                scl=1;
                somenop();
                j=sda;
                k=(k<<1)|j;
                scl=0;
                somenop();
        }
        return k;
}
void write_add(uchar x,uchar y)                //地址,写入
{
        I2Cstart();                                                //开始
        write_byte(0xa0);                                //器件地址 写入
        I2Cresponse();
        write_byte(x);                                //写入地址
        I2Cresponse();
        write_byte(y);
        I2Cresponse();                                                //写入数据
        I2Cstop();                                                //结束
}
void read_add(uchar x)//地址 读出
{
        I2Cstart();                                                //开始
        write_byte(0xa0);                                //器件地址 写入
        I2Cresponse();
        write_byte(x);                                   //写入地址
        I2Cresponse();
        I2Cstart();                                                //开始
        write_byte(0xa1);                                //器件地址 读出
        I2Cresponse();
        date=read_byte();
        I2Cstop();       
}
void init()                                //初始化
{
        time0=0;
        sec=0;
        read_add(0x06);
        sec=date;
        sda=1;
        scl=1;
        EA=1;
        ET0=1;
        TMOD=0x01;
        TH0=0x4c;
        TL0=0x00;
        TR0=1;       
}
void main()
{
        init();
        while(1)
        {
                display(sec);
                if(save==1)
                {
                        save=0;
                        write_add(0x06,sec);
                }
        }       
}
void timer0() interrupt 1 //定时器
{
        TH0=0x4c;
        TL0=0x00;
        time0++;
        if(time0==20)
        {
                time0=0;
                sec++;
                save=1;
                if(sec==100)
                {
                        sec=0;
                }
        }
}
用proteus模拟后用秒表同步测量了下,发现每5分左右会有1秒的误差。求解答

自己看书!

不至于这么准确吧

问题在你定时初值重装这里。
        TH0=0x4c;
        TL0=0x00;
定时器中断发生时定时器的初值是0x0000,以后定时器会从0x0000继续计数,并且在ISR中时定时器也不停止;所以当程序执行到ISR里面的初值重装语句的时,TL0已经不是0了,而你又直接把TL0赋值成0。这个时候就会少几个计数。
定时中断频率越高,误差越大。
解决方法:ISR中的初值重装使用TL0 += 初值。当这个初值很大时,要稍微做下处理,以防止TL0溢出,丢失计数。

明白了 十分感谢~

学习  学习

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

网站地图

Top