翻了以前的程序看了下,这个程序是不用实时时钟芯片来完成时钟功能的。和秒表对了一下时间,发现竟然在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),但是这样做感觉好心虚啊...感觉可能是我程序中存在一定问题,请各位指点啦!
- #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 编辑 ]
|