51单片机同时使用两个计时器的问题

遇到的问题是两个内部计时器同时使用会造成数码管无法正常扫描。
以下面程序为例,下面程序结果数码管(从0开始自加,8位数码管显示后4位)无法正常扫描,请问该如何修改?

#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define DATAPORT P0

uchar code NUMBER[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code POSITION[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
uchar TEMP[4];

uint num;

sbit duanma=P2^2;
sbit weima=P2^3;

void display(uchar first,uchar total)
{
static uchar i;

DATAPORT=0xff;
weima=1;
weima=0;

DATAPORT=TEMP[i];
duanma=1;
duanma=0;

DATAPORT=POSITION[i+first];
weima=1;
weima=0;

i++;
if(i==total) i=0;
}

void TIMER_ini()
{
TMOD |=0x11;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
TH1=(65536-2100)/256;
TL1=(65536-2100)%256;
EA=1;
ET0=1;
ET1=1;
TR0=1;
TR1=1;
}

void main()
{
TIMER_ini();
while(1)
{
TEMP[0]=NUMBER[num/1000];
TEMP[1]=NUMBER[num/100%10];
TEMP[2]=NUMBER[num/10%10];
TEMP[3]=NUMBER[num%10];
}
}

void TIMER0() interrupt 1
{
TH1=(65536-50000)/256;
TL1=(65536-50000)%256;
num++;
if(num>9999) num=0;
}

void TIMER1() interrupt 3
{
TH1=(65536-2100)/256;
TL1=(65536-2100)%256;
display(4,4);
}

就你现在的程序可以正常扫描显示的呀,就是有点闪烁的效果。
但不知道,这是和谁学习的,数码管显示要用定时器定时,中断一次显示一次,这可是仿真,运行速度肯定比实物要慢,所以,就会有闪烁的。
其实,你的主程序中有计算四位数的程序
TEMP[0]=NUMBER[num/1000];
TEMP[1]=NUMBER[num/100%10];
TEMP[2]=NUMBER[num/10%10];
TEMP[3]=NUMBER[num%10];
这是很费时的,这个时间足够显示一位的延时了,所以,就在主程序中调用显示子函数就很好的,何必还定时扫描呢。
这样
void main()
{
TIMER_ini();
while(1)
{
TEMP[0]=NUMBER[num/1000];
TEMP[1]=NUMBER[num/100%10];
TEMP[2]=NUMBER[num/10%10];
TEMP[3]=NUMBER[num%10];
display(4,4);
}
}
问题就解决了。
最后就一句,那计数是很快了,是每秒计一个数吗,还是就是计数?
这样改,要关掉定时器T1的中断。追问

谢谢,我的主要问题是数码管有闪烁。但请问一下同时用两个中断的话能否做到互不影响?这个问题是我在写超声波测距显示在数码管上的程序时碰到的,需要同时用两个中断,一个做计数器用来算时间一个做定时器用来扫描数码管。

追答

为什么非要“一个做定时器用来扫描数码管”呢?单片机的中断源不要做那些无关紧要的事情。数码管扫描放在主程序就能搞定的事,就不要用中断。当多个中断源,特别是扫描数码管的中断,因定时时间短,中断频繁,是会耗费单片机的时间的,各中断就会有影响的,得不偿失了。中断源互相影响这是克服不了的。如果是几个中断源都是必须的,可以分成不同优先级的。中断源多了,并不是一件好事。因单片机的运行速度毕竟是有限的,不能同电脑相比的。
当然这里还有一个事实,就是用仿真来调试程序,因运行速度慢,运行的结果会与实物有很大区别的。
如果你有实物板,或者就是为实际产品设计的程序,就不要用仿真来调试程序,就直接在实物上调试程序。就是算是在仿真里调试好了,但到了实物上运行结果还是不同的。所以,仿真调试程序等于走了弯路。
就你上面的程序,放在实物上运行,应该是可以,效果肯定是不同的,不然你就试试,上实物板上运行一下看看。

温馨提示:答案为网友推荐,仅供参考
第1个回答  2015-08-07
同时用两个中断肯定会冲突
定时器1完全可以不用,主程序只管显示就行,定时器0中断程序中更新计时数值
还可以尝试在定时器0的中断程序里关闭定时器1,交且将定时器0的中断优先级设高追问

不是,这个程序只是方便演示,其实是我在做超声波测距的时候遇到这个问题。请问用两个中断如何避免冲突呢?做数字钟的时候也遇到过这个问题。

追答

如果在定时器1的中断程序中关闭定时器0,会造成计时不准
扫描数码管,快一点慢一点都无所谓,不必用定时器1,并且中断函数尽量简短
我在红外线发射时用两个定时器时,一个是定时器0长定时MS级,另一个是定时器1短定时13US 短定时自动重装,只执行程序一个语句,使红外发射管电平翻转 
长定时中断也就一个话句,将一个标志置1 其余的都交给主程序作
总之是利用长定时控制短定时
在某段时间内允许定时器1和红外管工作,另一段时间不允许允许定时1和红外管工作
象你的定时器1的程序不是太长的话,可以夹在定时器0中断程序中,长的话加在主程序中
void TIMER0() interrupt 1
{
TH1=(65536-2000)/256;
TL1=(65536-2000)%256;
a++;
if(a==25)
{
num++;
a=0;
}
if(num>9999) num=0;
display(4,4)
}
中断程序里干这么多事,也不会超2ms(或4ms),主程序还有时间来分离num
最好还是将显示函数放在主程序中

本回答被提问者采纳
第2个回答  2015-08-07
display中真不知道你要干嘛,你只这样传递参数有何意义追问

可以任意控制8位数码管亮几个,44即第5678个亮,08即全亮,02即前两个亮。数码管不是重点,主要是两个计时器同时工作导致我数码管无法正常扫描

相似回答