说起按键程序,只要会单片机的肯定都很熟悉。一般开始学习单片机的时候,入门程序基本都是LED灯和按键。那么这个按键程序有什么特别的吗,还需要专门去思考吗?如果我刚开始学单片机的时候也会这么想,但是随着项目的积累,经验的增加,越来越觉得复杂的事情简单做,简单的事情复杂做
,这句话很有哲理,越是看起来简单的事情,真正做好却很不容易。下面就抽丝剥茧的来慢慢分析下这个按键程序有什么特别之处。
首先来看一下按键的硬件原理图。
这是一个很常见的按键硬件连接图,电源接一个上拉电阻,在接按键,按键的另一端接地,电阻和按键的连接点接到单片机的IO口。按键未按下的时候输出高电平,当按键按下的时候输出低电平。由于按键是机械开关,所以在按下的一瞬间可能会产生毛刺。按键的实际波形如下:
由于按键在按下或者弹起的瞬间会产生毛刺,所以在写程序判断的时候,需要加上10ms的延时。如果10ms后按键依然是低电平就认为按键有效,否则就认为出现了干扰,按键无效。
u8 key_scan(void)
{
if(key==0)
{
delay_ms(10);
if(key==0)
return 1;
else
return 0;
}
}
这种是很常见的方法,使用起来也最简单。看起来也没什么问题,现在将问题复杂化一下。假设按键被用户按下了一次,那么会有以下这些情况。
第一种情况是正常按键按下时间大概0.2秒左右,第二种情况是按键的时间非常短只有0.02秒,第三种情况是持续按下2秒。那么这三种情况都会被程序正常识别到。但是程序运行的结果可能会出现不同的效果。
假如现在的程序实现的功能是,在主程序中循环检测按键,如果发现按键按下,就让LED灯的状态翻转一下。也就是按一下按键LED灯亮,再按一下按键LED灯灭。程序执行流程如下。
void main(void)
{
char value = 0;
while(1)
{
value = key_scan();
if(value)
LED = !LED;
}
}
在主函数中一直循环检测按键,如果有按键按下,那么就翻转LED灯的状态。在实际测试过程中会发现按键有时候好像不怎么灵敏,当LED灯亮的时候,按一下按键,LED灯还是亮的。如果用示波器观察LED灯的波形,会发现按键按下一次时,LED的状态会翻转很多次。
按键按下的时候越长,LED翻转的次数越多。LED最后是亮还是灭就得靠运气了,通过按键很难控制一下灭,一下亮。那么为什么会出现这种情况。下面就根据波形分析一下程序执行的流程。
由于主程序干的事情很少,所以代码消耗的时间,主要是在按键检测的10ms中,也就是主程序基本10ms就能执行完一圈。假如按键按下的时间比较长,当按键程序检测完成之后,LED灯的状态也翻转了,此时按键依然没有弹起,那么程序会再次进入按键检测函数中。此时会再次检测到按键按下。这样LED灯在按键按下的这段时间中就会一直翻转。所以LED灯基本10ms翻转一次,由于人的视觉暂留时间时是20ms,翻转的时间小于20ms所以人眼看不到LED灯的闪烁。如果将按键的10ms延时改为100ms,那么在按键按下的时候,就会看到LED灯一直在闪烁。单次按键功能变成了连续按键的功能。
那么如果想要这个程序实现正常的功能要怎么办呢?第一种方法是在主程序中加入延时,让程序执行一圈花费的时间更多一点。第二种方法是按键检测的延时时间加长一点。第三种方法是当发现按键按下时直接进入死循环中,直到按键弹起,才退出按键检测程序。
前两种方法看着能解决问题,但是实际中不同的人按键的时间长短很难把握,有的人轻轻按一下,有的人使劲按半天。这样延时时间太长,感觉按键比较迟钝,延时时间太短,又会导致按一次按键,灯闪好几次的情况出现。这样同一个产品在不同客户的手里就有不同的客户体验,就会导致有的客户感觉产品的功能和设计的不符。那么最有效的解决方法只能是第三种,当按键按下后,等待按键弹起,然后在执行LED状态翻转的功能。
那么按键检测的流程改为下面这种:
u8 key_scan(void)
{
if(key==0)
{
delay_ms(10);
if(key==0)
{
while(key==0);
return 1;
}
else
return 0;
}
}
这样当按键按下的时候,就一直在while循环中等待按键释放。LED灯的状态在按键弹起的时候才会翻转。
不论按键按的快还是慢,LED的状态在按键的时候每次只会改变一次。这样就比较符合设计的期望。
但是这样又会引入一个新的问题,就是在按键按下的时候,程序就会一直停留在那里,其他的事情就不能干了。如果此时还有数码管动态显示函数,那么在按键按下的时候就数码管就会闪烁一下,如果按键按下时间很长,那么数码管就会熄灭。这样产品使用的时候体验就很不好。
那按键既不能在按下的时候让LED状态翻转,又不能在弹起的时候让LED翻转,难道就无解了吗?那这个LED灯如如何控制呢?要知按键如何判断?且听下回分解。
由一个按键程序引发的思考(中)