单片机新手,想做一个篮球的计时计分器。计时没有问题,就是每次按键加分计分的时候,会有抖动,然后我就加了延迟。但是加完延迟后,每按一次加分的键,所有的数码管都会闪一下。因为自己对延迟不是很懂,求大神帮忙QAQ,在此谢过。
附上原理图和源程序
#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar code Tab[]={0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71};
uchar ge,shi,num,count,sec,min,ge1,ge2,shi1,shi2;
uchar fen1,fen2;
uchar ge3,shi3,bai3,ge4,shi4,bai4;
sbit flag=P3^0;
sbit res=P3^1;
sbit P1_0=P1^0;
sbit P1_1=P1^1;
sbit P1_2=P1^2;
sbit P1_3=P1^3;
sbit P1_4=P1^4;
sbit P1_5=P1^5;
sbit P1_6=P1^6;
sbit P1_7=P1^7;
void delay(uint);
void key()
{
if(P1_0!=1){delay(1000);fen1=fen1+1;}
if(P1_1!=1){delay(1000);fen1=fen1+2;}
if(P1_2!=1){delay(1000);fen1=fen1+3;}
if(P1_3!=1){delay(1000);fen1=fen1-1;}
if(P1_4!=1){delay(1000);fen2=fen2+1;}
if(P1_5!=1){delay(1000);fen2=fen2+2;}
if(P1_6!=1){delay(1000);fen2=fen2+3;}
if(P1_7!=1){delay(1000);fen2=fen2-1;}
}
void pause()
{if(flag!=1) TR0=0;else TR0=1;}
void res_1()
{
if(res!=1) num=24; delay(5);
}
void main()
{
fen1=0;
fen2=0;
count=0;
num=24;
sec=0;
min=10;
P2=0x00;
TMOD=0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;
while(1)
{ key();
pause();
shi=num/10;
ge=num%10;
shi1=sec/10;
ge1=sec%10;
shi2=min/10;
ge2=min%10;
bai3=fen1/100;
shi3=fen1/10%10;
ge3=fen1%10;
bai4=fen2/100;
shi4=fen2/10%10;
ge4=fen2%10;
P2=0x00;P0=Tab[shi];delay(20);
P2=0x01;P0=Tab[ge];delay(20);
P2=0x02;P0=Tab[shi1];delay(20);
P2=0x03;P0=Tab[ge1];delay(20);
P2=0x04;P0=Tab[shi2];delay(20);
P2=0x05;P0=Tab[ge2];delay(20) ;
P2=0x06;P0=Tab[bai3];delay(20);
P2=0x07;P0=Tab[shi3];delay(20);
P2=0x08;P0=Tab[ge3];delay(20);
P2=0x09;P0=Tab[bai4];delay(20);
P2=0x0a;P0=Tab[shi4];delay(20);
P2=0x0b;P0=Tab[ge4];delay(20);
res_1();
}
}
void T0_time()interrupt 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
count++;
if(count==20)
{
count=0;
sec--;num--;
if(num>=24)
{
num=24;
}
if(sec>=59)
{
sec=59;
min--;
if(min==0)
{
min=10;
num--;
}
}
}
}
void delay(uint c)
{
uint a,b;
for(;c>0;c--)
for(b=5;b>0;b--)
for(a=2;a>0;a--);
}
同样非常很感谢你,解释地非常详细周到。
追答不客气,偶就是教这个的,所以话比较多哈。
其实你现在的主要问题是,对程序和物理现象的关系,理解得还不够
比如楼上的
if(P1_0!=1)
{
delay(10);
fen1=fen1+1;
while(!P1_0);
}
while(!P1_0);理解起来也没什么啊,
先看while(P1_0);
没有循环体的哦,所以是空循环
意思是,如果P1.0为“真”,就空循环
什么是为真,不等于0就是为真嘛
所以翻译起来就是,如果(P1.0==1),就空循环
那while(!P1_0);
翻译成中文就是,如果(P1.0==0)就空循环
再翻译一下,就是,如果(开关一直按着不放),就空循环
这是什么意思,就是如果开关如果没有松开,就卡在这个小小的空循环里等开关松开
那么,如果你一小时都不松开开关呢?那CPU就什么都不做,在这里等着
OK,那你的数码管当然不显示了
加上一句循环内容不一样了
if(P1_0!=1)
{
delay(10);
fen1=fen1+1;
while(!P1_0)
display();
}
这时候就不是空循环了,循环有了内容
什么内容呢?
每次循环,就调用一次显示函数
好理解吧
这样的话,如果按着开关不放,
程序还是会卡在这个循环里
可是不同之处在于,这个循环会调用显示函数
所以照样会显示数码管的内容。
其实这个很简单的
这样的理解过程是必须的,想多了,就容易了
学习单片机,学习别人的程序
一定要多思考
你做得项目越大,就会有越复杂越隐蔽的问题
需要你去考虑周全。
还有一点要提的是
你的程序,太乱了
可读性和可移植性都很差
程序的基本思路是,尽可能的条理清楚
不要把什么都写在main函数的主循环里
这样会很乱
要把各种功能都封装到函数里面
每个函数都有自己特定的功能
而主函数呢,在特定的时间,调用特定的函数完成任务
看起来就会清晰很多
程序流程一目了然,这就叫可读性强
而且下次你做别的任务时
以前的函数还是可以拿过来用,这就叫可移植性
都看完了,好多字啊,真的非常感谢您的指导和建议。
追答没事儿,现在不是放假么,我比较闲。
问题解决了,非常感谢你。能问问你为什么加了while(!P1_0)display();数码管就不会闪烁了?有点想不明白。
追答因为当你按住按键不松的时候while(!P1_0)一直为真,也就一直执行display(); 而display();是我常用的数码管显示函数
像你程序display()就是
void display(void)
{
shi=num/10;
ge=num%10;
shi1=sec/10;
ge1=sec%10;
shi2=min/10;
ge2=min%10;
bai3=fen1/100;
shi3=fen1/10%10;
ge3=fen1%10;
bai4=fen2/100;
shi4=fen2/10%10;
ge4=fen2%10;
P2=0x00;P0=Tab[shi];delay(20);
P2=0x01;P0=Tab[ge];delay(20);
P2=0x02;P0=Tab[shi1];delay(20);
P2=0x03;P0=Tab[ge1];delay(20);
P2=0x04;P0=Tab[shi2];delay(20);
P2=0x05;P0=Tab[ge2];delay(20) ;
P2=0x06;P0=Tab[bai3];delay(20);
P2=0x07;P0=Tab[shi3];delay(20);
P2=0x08;P0=Tab[ge3];delay(20);
P2=0x09;P0=Tab[bai4];delay(20);
P2=0x0a;P0=Tab[shi4];delay(20);
P2=0x0b;P0=Tab[ge4];delay(20);
}
单片机菜鸟求教,关于延迟和按键去抖的问题
同样周而复始。结果那1s时间内,什么都不显示,当然就看到数字不见了 解决办法就是采用定时器中断。不管是按键用中断也好,显示用中断也好,只要其中一个进入定时器中断,问题就解决了。程序就不写了,描述一下意思就好 你的主程序保留键盘部分,但是显示那一大段不要了 中断本来是50ms,建议改成20ms 然...
单片机 按键去抖啥意思???
单片机 按键去抖, 就是单片机的 按键 在正常操作中 在按压过程时 不能一下 完全接通,就是按压抖动,单片机在接收这种 信息时 会判断错误,所有要去掉这种抖动因素,去抖 有 硬件 去抖 就是在 按键与单片机连接的 IO 口 加 消抖电容 。还有 用 软件 去抖 就是 在单片机 接收按键 信息时 多次 ...
问一个关于单片机按键延时防抖方面的问题,使用软件防抖(汇编、C语言...
D2:DJNZ R6,D2 ;DJNZ R7,D1 ;RET D10mS就是一个延时程序,调用它后再进行判断电平判断,就避开了按键按下时的抖动.
单片机按键去抖动有哪些方法
在按键上增加电容去除干扰,在按键上串一个电阻也可以解决静电或者是其他干扰对按键造成的干扰。软件去抖动也是一种非常常见的去抖动的方法,就是对按键进行多次的检测,每次检测都被按下,才认为按键被按下。软件去抖动要采用多次采集的方法,中间的间隔可以使用延时或者使用分时的思想来进行去抖动,一般的...
单片机按键防抖动延时多长才合适
抖动一般是5~10ms,10ms可以,对时间没太大要求,大于10ms也可以比如20ms,不过太大了程序运行就费时间,看需求做吧。
在线采纳51单片机按键去抖的问题
我感觉多半是你得到的信息有误,应该没有这个技术。关于扫描,矩阵键盘需要用扫描的方式去监控,但是处理抖动仍然靠延时,延时至少是当下最有效的办法。抖动的实质是输入信号有高频杂波(相对于按键操作频率),目前只有滤波技术能消掉高频杂波。延时算一种数字滤波技术,当然还有硬件滤波技术,最简单的就是...
单片机键盘去抖动到底该用什么算法??!!
延时5-10ms再判按键
单片机的按键开关抖动的产生原因,抖动的特点和如何消除抖动
消抖的目的就是为了要除去信号在高低电位之间弹跳所造成的不正确输入,就是交错出现的01那段,一般抖动持续的时间是3-10毫秒。所以简单的去抖动操作,只要在这段抖动出现的时间跨度两端进行两次按钮状态检测即可:假设放开按钮信号为1,按下为0,那么当首次检测到按钮为0,过10ms再次检测,若依然为0,按...
单片机在扫描是否有键按下时,为什么要做这么多次的判断?有什么作用...
是为了防止键盘抖动,键盘抖动的时间是很短的,通过延时一段时间后,如果再判断键盘是按下的,这是才真正能说明键盘按下了,相反,则是抖动,不能说明键盘按下!所以,软件中一般都需要两次判断键盘按下!第一次之后,加段延时,之后再判断
AT89C51单片机:简述在使用普通按键的时候,为什么要进行去抖动处理,怎 ...
去除机械按键这种抖动的措施有硬件方法,还有软件方法,硬件方法就是在按键上增加电容去除干扰。在按键上串一个电阻也可以解决静电或者是其他干扰对按键造成的干扰。软件去抖动也是一种非常常见的去抖动的方法,就是对按键进行多次的检测,每次检测都被按下才认为按键被按下。