新手求助:数码管显示时候闪烁,找不到是什么原因,求高手们解析
下面是代码:
/*********************************************************************************
*实验名称:四位数码管计数器
*控制思路:使用定时器0不带中断控制数码管每秒加1
*实验效果:每过一秒,数码管累加1
*
*********************************************************************************/
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit DU = P2 ^ 6;
sbit WE = P2 ^ 7;
uchar code smgd[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
uchar buff[]={0xff,0xff,0xff,0xff};
void delay(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=112;j>0;j--);
}
void main()
{
uint cnt = 0;
uchar a = 0;
uchar x = 1;
uint sec = 0;
TMOD = 0x01;
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
TR0 = 1;
while(1)
{
if(TF0 == 1)
{
TF0 = 0;
cnt++;
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
if(cnt == 20)
{
cnt = 0;
sec++;
buff[0]=smgd[sec%10];
buff[1]=smgd[sec/10%10];
buff[2]=smgd[sec/100%10];
buff[3]=smgd[sec/10000%10];
}
if(a==0)
{
a++;
P0 = 0xff;
WE = 1;
WE = 0;
P0 = buff[3];
DU = 1;
DU = 0;
P0 = 0xef;
WE = 1;
WE = 0;
delay(x);
}
if(a==1)
{
a++;
P0 = 0xff;
WE = 1;
WE = 0;
P0 = buff[2];
DU = 1;
DU = 0;
P0 = 0xcf;
WE = 1;
WE = 0;
delay(x);
}
if(a==2)
{
a++;
P0 = 0xff;
WE = 1;
WE = 0;
P0 = buff[1];
DU = 1;
DU = 0;
P0 = 0xbf;
WE = 1;
WE = 0;
delay(x);
}
if(a==3)
{
a = 0;
P0 = 0xff;
WE = 1;
WE = 0;
P0 = buff[0];
DU = 1;
DU = 0;
P0 = 0x7f;
WE = 1;
WE = 0;
delay(x);
}
}
}
}
对了,我是希望用定时器0来定时1s,但是不开中断。不知道是不是没有中断后,main函数与定时器0同时运行才产生的问题?
对了,我是希望用定时器0来定时1s,但是不开中断。不知道是不是没有中断后,main函数与定时器0同时运行才产生的问题?
按你现在的定时数据算是50毫秒刷新一个数码管显示,时间太长了,缩短这个时间试试
首先,感谢你对我的问题做了回答,谢谢!
你说的50ms是说
TH0 = (65536-50000)/256;
TL0 = (65536-50000)%256;
这两句里面定时时间50ms其实是刷新数码管的时间吗?
我写时候,那个delay()是刷新数码管的,参数是2ms。
我按照你说的,把 TH0 = (65536-50000)/256改成了 TH0 = (65536-5000)/256(5万改成了5千,就是每次计时5ms)
也还是一样的效果,数码管还在闪
这里有几个问题:
一,你这里的delay(),不算是刷新延时,只是相邻两个数码管交替显示的间隔时间,因为你的所有程序都是在if(TF0 == 1)的条件下才执行,所以刷新时间是定时器的溢出时间。
二,定时器是执行加一操作直到溢出为0才产生中断,所以(65536-X)是计算定时起始值到溢出之间的数值,这个数值越小,代表定时时间越短。
三,最好是在定时器溢出时只显示一个数码管,等下次溢出时再显示下一个数码管,这样只有一个时间需要调整,容易做一些,象你现在的做法,实际上是有两个时间,一个是定时器,一个是delay(),两个时间的协调会比较麻烦
谢谢你耐心的教导。我理解了大概8成你说的,我自己再研究研究,这样弄懂了印象深刻一点。谢谢了!
多位数码管动态显示程序要掌握几个要点:
1.显示1轮的周期不大于15ms,不小于1ms,否则大于15ms会闪烁,小于1ms会暗淡并产生鬼影。每一位的显示时间1~3ms为宜。
2.各位显示时间应相同,否则各位亮度不均匀。
3.显示过程不能被其他程序干扰,会产生闪烁。避免使用软件延时delay占用MCU时间,会影响其他程序运行。
总而言之,用中断法或时间片轮询法处理多位数码管动态显示效果较好。
WE = 1;
WE = 0;
P0 = buff[3];
DU = 1;
DU = 0;
P0 = 0xef;
WE = 1;
WE = 0;
delay(x);
P0数显已经关闭,你又把IO口P2.7又是1又是0的,不是多此一举吗。另外,这代码也太烂了