单片机检测和处理按键时怎样不干扰数码管的显示?

用C语言编写一个定时器,基于STC89C52和四位动态显示数码管。现在的问题是当按下按键时数码管显示会变暗,分析原因应该是按键去抖时数码管无法显示所致。并且由于按键和显示是循环处理,所以只要按住按键不放就会不停动作。应该怎么处理?请大家提供一个相对简单的办法,谢谢!

这是我的程序(部分):
void main()
{
startled = 1; //开始LED熄灭

while(start!=0){ //开始键未按下时调时状态可用,最大定时99:59
if (minp10==0||minp1==0||secp10==0||secp1==0){
if(minp10==0){
delay(20); //去抖
if(minp10==0){
minh+=1;
if(minh == 10){
minh = 0;
}
}
}
if(minp1==0){
delay(20); //去抖
if(minp1==0){
minl+=1;
if(minl == 10){
minl = 0;
}
}
}
if(secp10==0){
delay(20); //去抖
if(secp10==0){
sech+=1;
if(sech==6){
sech=0;
}
}
}
if(secp1==0){
delay(20); //去抖
if(secp1==0){
secl+=1;
if(secl == 10){
secl=0;
}
}
}
}
display(minh,minl,sech,secl);
}

TMOD=0x01; //定时器工作在方式1 16位
TH0=0x3C; //50ms
TL0=0xB0;
TR0=1; //开启T0计时
ET0=1; //允许T0中断

EA=1; //开总中断

startled = 1;

while(1){
display(minh,minl,sech,secl); //显示时间数据
if(minh == 0 && minl == 0 && sech == 0 && secl == 0){ //计时结束时
EA = 0; //关总中断
TR0 = 0;
startled=1; //秒闪烁LED常亮
while(1){ //开始死循环
display(10,10,10,10); //计时结束显示"--:--"
}
}
}
}
这种动态扫描的程序有个缺点,就是要想正常显示CPU就不能执行其他工作。听说用定时器可以取代完成,要怎么做呢?

是按键的问题,你一直按着的时候 就一直死在那里,肯定会造成黑屏,你也没有处理防止一次按键多次响应的标志位,好像你写的好乱,没点思路一样,给你个程序让你参考下,希望你能看懂,这用了个锁存芯片573,但那个按键 是个蛮好的按键,可以参考下,觉得好的话给点分,我缺分,程序如下:
#include<reg52.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义

sbit KEY_ADD=P3^3; //定义按键输入端口
sbit KEY_DEC=P3^4;
sbit LED=P1^2; //定义led输出端口

#define DataPort P0 //定义数据端口 程序中遇到DataPort 则用P0 替换
sbit LATCH1=P2^0;//定义锁存使能端口 段锁存
sbit LATCH2=P2^3;// 位锁存

unsigned char code dofly_DuanMa[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};// 显示段码值0~9
unsigned char code dofly_WeiMa[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//分别对应相应的数码管点亮,即位码
unsigned char TempData[8]; //存储显示值的全局变量

void DelayUs2x(unsigned char t);//函数声明
void DelayMs(unsigned char t);
void Display(unsigned char FirstBit,unsigned char Num);
/*------------------------------------------------
主函数
------------------------------------------------*/
void main (void)
{
unsigned char num=0;
KEY_ADD=1; //按键输入端口电平置高
KEY_DEC=1;
while (1) //主循环
{

if(!KEY_ADD) //如果检测到低电平,说明按键按下
{
DelayMs(10); //延时去抖,一般10-20ms
if(!KEY_ADD) //再次确认按键是否按下,没有按下则退出
{
while(!KEY_ADD);//如果确认按下按键等待按键释放,没有释放则一直等待
{
if(num<9) //加操作
num++;

}
}
}

if(!KEY_DEC) //如果检测到低电平,说明按键按下
{
DelayMs(10); //延时去抖,一般10-20ms
if(!KEY_DEC) //再次确认按键是否按下,没有按下则退出
{
while(!KEY_DEC);//如果确认按下按键等待按键释放,没有释放则一直等待
{
if(num>0) //减操作
num--;
}
}
}
TempData[0]=dofly_DuanMa[num%10];
Display(0,1);
//主循环中添加其他需要一直工作的程序

}
}
/*------------------------------------------------
uS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编,大致延时
长度如下 T=tx2+5 uS
------------------------------------------------*/
void DelayUs2x(unsigned char t)
{
while(--t);
}
/*------------------------------------------------
mS延时函数,含有输入参数 unsigned char t,无返回值
unsigned char 是定义无符号字符变量,其值的范围是
0~255 这里使用晶振12M,精确延时请使用汇编
------------------------------------------------*/
void DelayMs(unsigned char t)
{

while(t--)
{
//大致延时1mS
DelayUs2x(245);
DelayUs2x(245);
}
}
/*------------------------------------------------
显示函数,用于动态扫描数码管
输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示
如输入0表示从第一个显示。
Num表示需要显示的位数,如需要显示99两位数值则该值输入2
------------------------------------------------*/
void Display(unsigned char FirstBit,unsigned char Num)
{
unsigned char i;

for(i=0;i<Num;i++)
{
DataPort=0; //清空数据,防止有交替重影
LATCH1=1; //段锁存
LATCH1=0;

DataPort=dofly_WeiMa[i+FirstBit]; //取位码
LATCH2=1; //位锁存
LATCH2=0;

DataPort=TempData[i]; //取显示数据,段码
LATCH1=1; //段锁存
LATCH1=0;

DelayMs(2); // 扫描间隙延时,时间太长会闪烁,太短会造成重影

}

}
温馨提示:内容为网友见解,仅供参考
第1个回答  推荐于2017-11-23
程序乱了一点,重新调整一下结构吧,你可以试一下这样:你的4位数码管还是用动态扫描,4个以内的按键也还是用扫描,不过你要把几个按键的扫描时间安排在4个数码管的显示时间内,即是显示第一位数码管后就扫描第一个按键状态,判断按键的不同状态(开或合)给予不同的标志(这个标志用来后面程序统一处理按键的动作的);当显示第二位数码管后就扫描第二个按键的状态,判断按键的不同状态(开或合)给予不同的标志...以此类推,当4个数码管都显示完后就放一段按键的处理程序(根据不同的标志作出不同的处理),到此再返回开始处循环.本回答被提问者采纳
第2个回答  2017-11-17
按键消抖不要采用延时来实现,
懂事电子设计 Vgz

单片机检测和处理按键时怎样不干扰数码管的显示?
程序乱了一点,重新调整一下结构吧,你可以试一下这样:你的4位数码管还是用动态扫描,4个以内的按键也还是用扫描,不过你要把几个按键的扫描时间安排在4个数码管的显示时间内,即是显示第一位数码管后就扫描第一个按键状态,判断按键的不同状态(开或合)给予不同的标志(这个标志用来后面程序统一处...

单片机检测和处理按键时怎样不干扰数码管的显示?
输入参数 FirstBit 表示需要显示的第一位,如赋值2表示从第三个数码管开始显示

单片机 按键控制8位数码管显示问题
通常可以是把全部数码管位全部显示为空的状态,谈后在开下一个位的显示(有延时),这样在开下一个位的锁存时上一个位的数据就不会跑到该位显示,不然会在下一位显示时会与上一个位的数字出现重影现象。。。

关于STC51单片机按键影响数码管亮度的问题
不知道你的是汇编语言写的程序还是用C语言写的,问题出在当按下按键时,你的程序是在等待按键释放吧,不再去执行显示子程序了,所以,才出现这种情况。你可以在等待按键释放的同时调用显示子程序。假设按键定义为ins1,显示子程序是display(),可以这么写:if(ins1==0){ 想要写的语句;while(ins1=...

...为什么在按下独立按键的时候会出现闪烁?怎么回事?
因为你按键的时候影响了数码管刷新;数码管一般都是动态扫描的,利用人眼的视觉暂留做的,你按下按键的时候,肯定有延时消抖,延时的时候就影响了数码管显示,所以数码管刷新的慢了,人眼就能分辨出来亮和灭的状态...解决办法 1、改进按键扫描 2、改进数码管显示 3、用嵌入式系统 以上三选一即可解决 ...

单片机数码管动态显示的过程中,怎么实现让其中一个闪烁,其他的不受影...
1 单片机数码管动态显示的过程中,设置一个闪烁寄存器,专门保存要闪烁显示的位子,再增加一个闪烁显示码的暂存器。2 每次调用显示程序时,先要判断需要显示闪烁的位子的显示码,是不是等于“灭”的显示码,不是的话,将该位的显示码送闪烁显示码的暂存器进行保存,将“灭”的显示码送入相应的显示缓冲...

单片机菜鸟求教,关于延迟和按键去抖的问题
你的主程序保留键盘部分,但是显示那一大段不要了 中断本来是50ms,建议改成20ms 然后呢,设置一个变量,每次进入中断就把变量的值加1 加完以后,根据变量当前的值,控制数码管显示\/关掉一位 大概就是这样的 void T0_time()interrupt 1 { TH0=(65536-20000)\/256;TL0=(65536-20000)%256;\/\/从...

51单片机按键时,数码管会闪烁一下.原因是什么
原因很简单,这是代码和数码管驱动的问题 按键会影响数码管显示,这是单片机直接驱动数码管会出现的问题,而数码管则是工作在动态扫描方式的,若是采用带有锁存器件的数码管驱动,则不会出现此类现象,因为单片机是周期性的扫描工作方式,单片机直接驱动数码管的电路,当单片机扫描到按键的时候,数码管部分...

单片机电子时钟按键按下数码管会闪烁一下怎么办
你程序设计的问题,编程思路不够严谨合理,按键扫描一般在打开显示时加入,扫描程序尽量简短高效,,因为打开显示的时候是要延时一点点时间再关闭,再进行下一行 led 的扫描, 所以把按键扫描程序当作延时,也是很好的办法.

单片机实验中数码管显示出现拖影的原因及解决方法
数码管残影的产生,只发生在动态扫描的设计电路中,主要问题是软件设计者考虑不足引起的。残影产生的原理是:在程序进行切换数码管显示时,旧数据(上一位数码管的段选数据)依然存在,就开启了新数码管的位选,导致 旧数据 在 新数码管 短暂出现,然后程序更换新数据,替换了 旧数据。反复快速的进行...

相似回答