单片机按键检测。。。谁有办法做到既能准确只改变一次数值,又不失响应速度。求算法。。。。。
发布网友
发布时间:2022-05-21 19:20
我来回答
共5个回答
热心网友
时间:2023-11-07 20:20
检测到按键被按下后,在消抖延时的过程中反复检测,若延时过程中按键松开(或弹开),则退出,直到再次检测到按键被按下.
并且,关键是,消抖延时最好利用定时中断来做,这样的话,在消抖的过程中,也不会影响其它的工作.
我的一般做法是,将定时器设定为1mS中断一次,假如你采用15mS做按键消抖,那就在按键检测程序中检测到按键被按下时,设一个标志位,然后1mS之内就会进定时中断,在中断中判断按键是否继续被按下,若是,则对一个寄存器加一,若不是,则清除按键的标志位和该寄存器.若寄存器计到15了,就表示该按键已经持续了15个mS是有效的,可以判断为一次有效按键了.
这样做的好处在于,由于在中断中只是判断和设定一两个标志位,因此占用的中断时间很少很少,剩余的时间就可以退出中断去继续干别的.
并且,这个1mS的定时时间,还可以作为系统中其它功能的一个"时基",也可以理解成软件的"节拍",对这个1mS进行计数,可以得到任何想要的定时标志,例如10mS、100mS、1S等等,这对于很多软件来说,比单纯的一个大循环要好调配得多,并且还容易找出有冲突的地方,便于维护和升级.
当然,对于不同速度的芯片来说,定时器1mS的定时周期或许不太合适,那也可以改为2mS或5mS,反正是便于计数和计算的一个基础值就可以.
希望对你有用^_^
--------
按一次会连续加几次的问题,是因为你没有对按键的"松开"进行判断.
也就是说,按键按下后,执行过一次了,就设定一个标志位,直到该按键被松开,才清除这个标志位.这样的话,当再次执行到该按键的时候,就可以判断这一次按键有没有执行过,也就是,这一次按键"有没有用过".用过了就跳过,没用过才用.追问可是我的两个定时器中断都用了。。。我用了一个250MS的定时器读取时钟芯片里的数据,还有一个定时器16ms中断用来送数码管显示了。。。您的这个方法让我想到了一个办法。。我先试试。。
追答16mS送显示,你可以用对1mS进行计数来得到16mS啊,250mS也可以对1mS进行计数啊,这样的话你就只需要用到一个定时器了.
热心网友
时间:2023-11-07 20:20
按键多不多?
不太多的话提供一个我自己搞过的算法,几乎不丢失响应速度。
你定义一个变量 假设x。用来存储检测到的按键状态。
我通俗点说 第一次检测到按键是通 ,将x加1.然后不管了,继续走其他程序, 跑完一次整个程序,第二轮检测按键,如果是通,再加1,如果是断 将x置零。继续走其他程序。
这样,如果x没有变为零 而是一直加啊 加啊 x到达某个数值的时候,你就认为按键有效了。具体的值要看你的程序一圈多少时间消耗。假设你的程序1ms一圈,那么你的x到了10,就等同于delay(10)了,对吧,而且中间你也没有停顿再那里。继续在做事情。
希望能帮助你。以前也困扰我几天才想出来的主意。
我晕,就一个按键。还以为你的系统很复杂,CPU没时间。 按几次是因为你按的时间远远大于你X的周期了。尽量将x设置大一点的时候有效。不过就一个按键,一个循环才几个微妙确实蛋疼了。你在给x+1之后,加入一点适当的延迟吧。至少要让x代表的时间大于你手按下,松开的时间就可以了。
热心网友
时间:2023-11-07 20:21
void KeyScan()
{
uchar TempKeyValue;
if(Key1 ==0)
TempKeyValue | = 0xfe;
if(Key2 ==0)
TempKeyValue | = 0xfd;
if(KeyScanBuf == TempKeyValue)
{
g_TrgKey = KeyScanBuf & (KeyScanBuf ^g_TrgCnt);
g_TrgCnt = g_TrgKey;
}
eles
{
KeyScanBuf = TempKeyValue ;
g_TrgCnt = 0;
g_TrgKey = 0;
}
}
//未定义变量为全局变量,此程序每10ms调用一次即可,如需扩展,在按键判断时判断即可
写代码,特别是8位单片机的代码,你始终要明白,它的效率只有那么高,所以程序中不要出现超过1ms的死延时,否则严重影响效率,所有的代码都可以用轮询方式完成,实时性强的可中断内完成。按照这个代码,保证你的按键灵敏,且不影响其他程序的运行
热心网友
时间:2023-11-07 20:21
加多一层判断即可
if(Key_OK)//可以识别按键标识
{
if(K1==0)
{
delay(10);
if(K1==0)
{
a++;
Key_OK=0;//关闭按键识别
}
}
}
if(K1) Key_OK=1;
热心网友
时间:2023-11-07 20:22
为你献上程序
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit d1=P1^0;
sbit la=P2^6;
sbit wela=P2^7;
sbit key1=P3^4;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void main()
{
wela=1;
P0=0xfe;
wela=0;
P3=0xff;
while(1)
{
if(key1==0)
{
delay(5);
if(key1==0)
{
d1=0;
num++;
if(num==10)
num=0;
}
while(!key1);// 松手检测
delay(5);
while(!key1);
}
else
d1=1;
la=1;
P0=table[num];
la=0;
}
}