3637|2

64

帖子

0

TA的资源

一粒金砂(高级)

楼主
 

如何提高这个时钟程序的精度呢? [复制链接]

翻了以前的程序看了下,这个程序是不用实时时钟芯片来完成时钟功能的。和秒表对了一下时间,发现竟然在1分钟内慢了4秒钟,顿时纠结了=。=

于是我决定思考、调试一下视图解决这个问题。这个程序是利用单片机的定时器中断来完成简单的时钟功能的。

定时器中断标志位为count,刚开始程序的定时器计数初值设置的是50ms,count==20的时候把秒数++,以此类推。根据计算数值,确实是1s无误=。=

于是思考了一下原因,为什么这样会比实际的时间慢呢?肯定是在count每50ms就加1的时候出现了遗漏,这样就造成了秒数升的慢,比实际时间要慢。

对于产生漏加count的原因,我开始了思考。原来main函数里面我把对计数的判断都放在其中,如if(count==20)count=0;count++;这时我想是不是主程序过长,导致出了中断之后,没有遇到这个判断,导致漏加了?于是我把那些判断语句都放在了中断程序中,可是误差依然存在,并且一点都没有减少!仍然是4s钟=。=

问题1:如果中断程序在进行中,定时器还在进行定时计数么?我把判断语句放在了中断程序中,为什么不能减少误差,这样做对么?

问题2:各位前辈是如何解决这类计时不准的问题呢?

PS:我自己后来调了一下定时器初值和count判断的值,实现了段时间内无误差(计数初值设置25ms,count判断37),但是这样做感觉好心虚啊...感觉可能是我程序中存在一定问题,请各位指点啦!

  1.  

复制代码

  1. #include<reg52.h>
    #include<intrins.h>
    sbit dula = P2^6;
    sbit wela = P2^7;
    sbit rs = P1^0;
    sbit rw = P1^1;
    sbit en = P2^5;
    #define _NOP_10us _nop_();_nop_()
    unsigned char count ,miao, fen, shi;
    unsigned char miao1, miao2, fen1, fen2, shi1, shi2, num;
    unsigned char code table3[] = {'0','1','2','3','4','5','6','7','8','9'};

    /*********500us延时函数*********/
    void nop500us()
    {
    int i;
    for(i=0;i<50;i++)
    {
    _NOP_10us;
    }
    }

    /*******1602液晶写命令函数********/
    void writecom(unsigned char com)
    {
    rs = 0;
    rw = 0;
    en = 0;
    P0 = com;
    en = 1;
    nop500us();
    en = 0;
    }

    /*******1602写数据函数*************/
    void writedat(unsigned char dat)
    {
    rs = 1;
    rw = 0;
    en = 0;
    P0 = dat;
    en = 1;
    nop500us();
    en = 0;
    }

    /***********初始化函数**************/
    void init()
    {
    EA = 1;
    ET0 = 1;
    TMOD = 0X01;
    TH0 = (65536-25000)/256;
    TL0 = (65536-25000)%256;
    TR0 = 1; //定时器初值中断设置
    dula = 0;
    wela = 0; //关数码管段选位选以防干扰。附加问题1处,此处虽然关了数码管段选位选,但为何数码管还是会被影响?
    writecom(0x38);
    writecom(0x0c);
    writecom(0x06); //写1602命令字,开显示,不显示光标,不屏移

    count = 0; //各种变量初始化
    miao = 0;
    fen = 0;
    shi = 0;
    miao1 = 0;
    miao2 = 0;
    fen1 = 0;
    fen2 = 0;
    shi1 = 0;
    shi2 = 0;
    }
    void main()
    {
    init();
    writecom(0x80+0x49); //写冒号
    writedat(':');
    writecom(0x80+0x46);
    writedat(':');
    while(1)
    {
    writecom(0x80+0x44); //写小时位的两位数
    writedat(table3[shi1]);
    writedat(table3[shi2]);

    writecom(0x80+0x47); //写分钟位的两位数
    writedat(table3[fen1]);
    writedat(table3[fen2]);

    writecom(0x80+0x4a); //写秒数的两位数
    writedat(table3[miao1]);
    writedat(table3[miao2]);
    }
    }

    /***********定时器0中断函数***********/
    void timer0() interrupt 1
    {
    TH0 = (65536-25000)/256;
    TL0 = (65536-25000)%256;
    count++;
    if(count == 37) //主要问题处,如何提高计时精度呢?此处我自己调试设置为37,短时间内没有发现误差..
    {
    count = 0;
    miao++;
    }
    if(miao == 60)
    {
    miao = 0;
    fen++;
    }
    if(fen == 60)
    {
    fen = 0;
    shi++;
    }
    shi1 = shi/10;
    shi2 = shi%10;
    fen1 = fen/10;
    fen2 = fen%10;
    miao1 = miao/10;
    miao2 = miao%10;
    }
复制代码
[ 本帖最后由 qrswll 于 2012-6-14 10:43 编辑 ]
此帖出自单片机论坛

最新回复

当定时器产生中断,直到这个中断被cpu处理(即转到中断处理程序),这个过程中定时器没有停止,而是一直在增加,那么这段时间就被忽视了,中断程序里置定时器初值时应该微调。比如:TL0 = (65536-25000)%256;换成TL0 |= (65536-25000)%256;其实不用实时时钟很难精准,毕竟一般晶振是有很大误差的  详情 回复 发表于 2012-6-14 20:39
点赞 关注
 

回复
举报

6366

帖子

4892

TA的资源

版主

沙发
 
定时器中断定时的时候,要考虑中断程序里面的指令延迟,要计算你的中断用了多少个指令周期,然后在定时时间里把这个时间补偿一下
此帖出自单片机论坛
 
 

回复

239

帖子

0

TA的资源

一粒金砂(高级)

板凳
 
当定时器产生中断,直到这个中断被cpu处理(即转到中断处理程序),这个过程中定时器没有停止,而是一直在增加,那么这段时间就被忽视了,中断程序里置定时器初值时应该微调。比如:TL0 = (65536-25000)%256;换成TL0 |= (65536-25000)%256;其实不用实时时钟很难精准,毕竟一般晶振是有很大误差的
此帖出自单片机论坛
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/10 下一条
【干货上新】电源解决方案和技术第二趴 | DigiKey 应用探索站
当月好物、电源技术资源、特色活动、DigiKey在线实用工具,干货多多~

查看 »

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网 12

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表