一般的单片机开发板,用的按键是普通的按键开关。其结构为弹簧铁片,按下时铁片导通两端电路,松开时铁片由于弹簧作用断开两端电路。这样的普通按键存在一个弊端,就是人的手在按下的时候,由于不能直接导通,可能会由于存在氧化、杂物(灰尘)、人体颤抖等等使其产生一个震荡电路。说白了就是按下的时候,不只是一个电平变化,而是一系断开闭合的方波。而单片机的处理速度是ms级,也就是说它会把这个变化算为一个信号输入。为了避免这个,就用软件的方式,即按下按键后开始延时,延时20ms后(抖动期过后),仍然检测为按下,就说明真的按下,并且只按下一次。那么就进入按键程序了。。
如果没有延时程序,那么当你按下时,i可能不是++ 而是 i++很多次,可能是10次或者20次。更多
也即是说Delay(一个很大值)时,需要长按键盘才算真的按了一次键盘?
如果在延时中,你松开了。延时结束时程序会判断为你没按。。如果在延时中你松开了,但是在延时结束前你又按下了。还是会判断为你按了。。
这样就懂了,还是你回答的比较好,一针见血。谢谢
有什么软件可以延时拍照 比如 我按下快门后十秒或者五秒后自动拍照
叫延时拍摄功能,基本都具有,可以看看说明书更多
找是找到了,不过
延迟八秒拍成这样
不过还是谢谢你,我已经用其他方式解决了☺
嗯,不用互相帮助也是应该的
单片机消抖延时程序
#include<reg52.h>
bit KEYFlag = 1; //指示按键状态,'1'为弹起态,'0'按下态
/********************************
按键去抖
*********************************/
void KEYDelay()
{
unsigned char i = 200;
while(i--);
}
/********************************
键翻译
*********************************/
unsigned char KEY_Tran(unsigned char Key)
{
switch(Key)
{
case 0xee: return 0; break; //根据按键编码返回对应的键值
case 0xde: return 1; break;
case 0xbe: return 2; break;
case 0x7e: return 3; break;
case 0xed: return 4; break;
case 0xdd: return 5; break;
case 0xbd: return 6; break;
case 0x7d: return 7; break;
case 0xeb: return 8; break;
case 0xdb: return 9; break;
case 0xbb: return 0x0a;break;
case 0x7b: return 0x0b;break;
case 0xe7: return 0x0c;break;
case 0xd7: return 0x0d;break;
case 0xb7: return 0x0e;break;
case 0x77: return 0x0f;break;
default: break;
}
}
/********************************
键扫描
*********************************/
unsigned char KEY_Scan()
{
unsigned char KEY_Value;
P2 = 0x0f;
KEY_Value = P2;
P2 = 0xf0;
KEY_Value |= P2;
return KEY_Value;
}
/********************************
查键
*********************************/
void KEY()
{
static bit KEYFlag = 1;
static unsigned char KEYCode;
if(KEYFlag)
{
if(KEY_Scan()!=0xff)
{
KEYCode = KEY_Scan();
KEYDelay();//有按键按下延时去抖
if(KEYCode==KEY_Scan())
{
// 键号 = KEY_Tran(KEYCode);
// 此处添加功能模块
KEYFlag = 0;
}
}
}
else
{
if(KEY_Scan()==0xff)
{
KEYDelay();//按键弹起延时去抖
if(KEY_Scan()==0xff)
KEYFlag = 1;
}
}
}
一个51单片机交通灯C程序,这个程序里面按键消抖和数码管都是用软件延时,用定时器0来怎么做C程序
给个定时器的示例你看看
#include<reg52.h>
sbit led = P0^0;
unsigned int num;
void main(void)
{
TMOD = 0x00; // 工作方式0
TH0 = (8192 - 5000) / 32; // 12M晶振下定时5ms
TL0 = (8192 - 5000) % 32;
EA = 1; // 开总中断
ET0 = 1; // 开定时器中断
TR0 = 1; // 启动定时器
while(1)
{
if(num == 200) // 定时1秒钟到
{
num = 0; // 计数器清零
led = ~led; // led灯取反,实现1秒闪烁一次
}
}
}
void timer() interrupt 1
{
TH0 = (8192 - 5000) / 32; // 重装初值
TL0 = (8192 - 5000) % 32;
num++; // 计数器加1
}
可以看一看
51单片机软件方式按键消抖
编写消抖程序,我的思路是这样子的:使用定时器0延时10ms
程序在初始化之后,执行的就是判断p1.0引脚电平状态的指令,如果p1,0是低电平,那么就启动定时器0,开始计时,那么此时主程序应该干什么呢?
是原地等待还是继续检测p1.0的状态呢?
--P1.0,可以不检测了,因为已经启动了定时器。
--可以检测其它接口。
--如:串口、AD转换接口、温度检测、烟雾报警接口、红外输入接口...
--也可以输出,动态数码管显示...
定时时间到之后,在中断服务程序中检测p1.0的状态,如果是低电平,则说明按键按下了,就执行相应的子程序,执行完子程序之后呢?程序是否返回了中断服务程序的位置,继续执行呢?
--回到发生中断的地方。
如果是高电平的话,就退出中断服务程序,那么退出之后怎么办?
--回到发生中断的地方。
--没有了定时,应该继续执行检测p1.0状态。
看一下我在下面的中贴出的程序,在MAIN中,检测到p1.0是低电平的时候,启动定时器,然后就进入了原地等待的指令;
定时时间到了之后,如果p1.0为低电平,就执行相应的程序,如果是高电平,就退出中断了,但是退出之后,执行的依然是原地等待命令,我希望是继续检测p1.0的状态;
使用定时器延时的时候,这个程序就存在这个问题,但是如果使用空循环延时的话,就能够写出来了,希望能针对我的程序给出几点建议;
检测到p1.0是低电平的时候,启动定时器,然后就进入了原地等待的指令;
----
老等那行?
还得循环的检测。
前面已经说了:
--P1.0,可以不检测了,因为已经启动了定时器。
--可以检测其它接口。
--如:串口、AD转换接口、温度检测、烟雾报警接口、红外输入接口...
上面说的,已经包括检测定时器是否停止。
当定时中断结束后,应有令 TR0 为零的语句。
当 TR0 为零后,就继续检测 P1.0。
添加一段延时程序来消除按键抖动,求助大神
在JZ LOOP1之后加:
call delay;延时
MOV A,P3;再次读取P3状态
CPL A
JZ LOOP1 ;判断,真按下了往下走,否则 返回LOOP1处
LOOP2:⋯⋯
单片机键盘去抖动c语言程序!!!
首先,你把你的想法说说,漏洞在哪?这样我们才能有针对性的回答
其次,用延时程序去抖动。去抖动主要是当你按下按健时,由于按健有反应时间、有抖动,可能你按一次机器感应到几次。所以用延时程序防抖就是让在手指按键(按下,松开的间隔)正常反应时间即10ms(参数具体自己调),确定只有一次按键 。去除过程中的毛刺等因素更多
我不懂为什么你和iamlaosong 都觉得程序没问题。
if(key1==0)
{
delay(5);
if(key1==0) 这里为什么要再判断一次?如果delay(5)之后还是抖动波形,那么key1可能是高电平,直接跳过if,到while(), 等松手之后进行下一次检测。可是!这之中num并没有经过num++啊,也就是按了一下,但没有num的自增;如果认为delay(5)之后已是低电平,何须判断if(key1==0)呢
请看我对iamlaosong的回复,字数有限制
delay(5) 为手指按键(按下,松开的间隔)正常反应时间。意思就是你手指按下去到松开,基本要花费delay(5) 的时间
而按下去的过程中,有毛刺,有抖动波形。一发生毛刺现象,如果按正常的检测程序(key1==0)就会检测到两次。
用
if(key1==0)
{
delay(5);
if(key1==0) 程序,就能很好避免这个情况。至于你说的,1、if语句时候刚好是高电平,工程上讲这个概率非常小。但是出现毛刺的概率非常大。2、如果认为delay(5)之后已是低电平,何须判断if(key1==0)呢?这个就是为了防止是毛刺现象啊,如果是毛刺在delay(5)仍是高电平。你怎么就知道是按下去,而不是毛刺呢。
我觉得你的想法,带有一种先入为主的思想,你应想想,出现毛刺了,你怎么消除??
要我说,你自己试验一下不就完啦,用示波器看看波形,看看按键结果。实验是检验真理的唯一标准
谢谢!我对iamlaosong 的回复打错一个字:如果delay(5)之后还是抖动波形,且if语句时候刚好是。。低。。电平 ?
据你说的理解,是不是可以这样说呢:
delay()函数必须延迟非常准确,以至于保证能够大于抖动时间;这样经过delay()之后就不可能有抖动波形,而只能有各种因素(如器件、温度等)造成的短暂毛刺?!
而所有的delay(),if,while(!k)之类的,都仅仅是用于防止那些短暂的、不是由于抖动造成的毛刺?
是的
你最好,试验一下。
因我没有板子。。
既然这样我要继续问你一下,
whle(!key1)
delay(5)
whle(!key1)
这段也有问题啊,比如你手按的时间很长,当中突然有个毛刺瞬间高电平,于是跳到delay;但注意此时手一直是按着的,delay结束后仍然低电平,进入第二个whle,注意,此时的状况与第一个whle完全一样!很可能再来一个毛刺跳过第二个while,这工程上完全可能啊,这时因手一直按着,可导致num++多次啊!哪怕第二个whle不是毛刺也无法去除松手的抖动啊!
是有可能啊,但是概率是多少呢?
是小概率事件啊,同志,基本可忽略。
不是,你没理解我意思。第一个while测试的时候,怎么会发生毛刺???如果你认为毛刺本身是小概率时间,那就可以省略第二个while啊;如果认为第二个while是怕第一个while被毛刺退出,那么没有理由认为第二个while不会同样发生毛刺。那么难道你认为发生一个毛刺是大概率时间,两个毛刺以上则为小概率事件??显然不能苟同吧。。 或者你说说毛刺对于这个测试,发生的概率随时间的分布函数?
认为毛刺本身是小概率时间
————————————————————
是毛刺,手的抖动刚刚发生在这个时间点,是一个小概率事件。
比如说delay(5)这个时间段与一个时间点相比,你觉得发生概率大还是小。
毛刺的发生,手的抖动是个随机事件。
你就不明白我的意思,你就不能好好看我的话。
说真的,我们说一百遍,不如实验做一遍
你按自己的想法写个程序,不就完啦,有些东西,实验做多了自然而然就明白了,光靠看,光看想,看不明白,想不明白,弄不明白
我当然认真看你的回复的。。你也再好好看我的。。你似乎还是没理解我意思,还是我之前你的问题。你说“delay(5)这个时间段与一个时间点相比…” 我觉得你是搞错了,毛刺并不是在delay()结束的瞬间有效。因为手一直按着,只要有毛刺就能检测的。
while(!key1); //手按着,低电平,万一有毛刺
delay(5);
while(!key1);说的是这段,万一又有个毛刺,手还没松呢;就算没毛刺,松手之后的抖动会触发num++
我没版子。。
while(!key1); //手按着,低电平,万一有毛刺
delay(5);
while(!key1);说的是这段,万一又有个毛刺,
哦,这样就出错了。
呵呵,手一直按着来计数,呵呵。
囧。。你是想说一般不手一直按着吗?但我并不是说手故意一直按着啊,只是相对毛刺的时间,手按得时间可能长呢?否则你干嘛在delay(5)之后再while?注意第二个while就是怕手还按着才写的啊!!!这时哪怕没毛刺,手一松不就出问题了么(没有delay)?我说的有错么……
转载请注明出处51数据库 » 延时去抖用什么软件 单片机的软件消抖什么意思