按键简介
51上的按键又名“轻触按键”、“轻触开关”(实际上按着挺费劲的,还有点费手),一种电子开关,在电路中按下导通、松开断开。
原理是通过按压柱塞,使按键内部的金属簧片(反作用弹簧)形变,使接点相接触,以此导通电路。
按键结构
按键拆解结构如图:(拆了两个,经费爆炸啊同伙们!)
ps:注意端子与接点的连接状态;1和4初始导通、2和4初始导通,1和2初始不导通、3和4初始不导通;按下的时候,簧片被压扁,3个接点全部被连接在一起,4个端子也就都连接在一起、互相导通了(很巧妙的设计,有没有?)。
使用and消抖处理
“得益”于按键的设计,当断开、闭合时,由于簧片的弹性作用,在闭合时不会马上稳定地接通,在断开时也不会一下子断开,而在闭合及断开的瞬间均伴随有一连串的抖动,为了消除抖动所带来的不良影响,所做的措施就是按键消抖。
下图是按下时电平的波形图(字丑勿喷,狗头保命):
抖动时间的长短由按键的机械特性决定的,一般为 5ms 到 10ms。按键稳定闭合时间的长短则由操作人员的按键动作决定的,一般为零点几秒至数秒。按键抖动会引起按键被误读多次。为了确保 CPU对按键的一次闭合仅作一次处理,必须进行消抖。
按键消抖有两种方式,一种是硬件消抖,另一种是软件消抖。为了使电路更加简单(为了更便宜),通常采用软件消抖。51开发板也是采用软件消抖,一般来说按键消抖就是先检测按键的状态(电平高低),如果得到按键状态(电平)改变之后,延时一段时间(我是11ms,保险一点),再次读取按键的状态(电平),如果按键状态(电平)是改变后的,那么说明按键已经按下或者松开。
各种简单应用及代码
肯定有更加牛(简单、稳定、高效)的消抖代码,我也懒得去求大佬要源码了,各位同伙有兴趣的话就自己研究去吧。
下图是普中51单片机的按键电路图:
注意P3^1和P3^0的位置,啧啧,这么多年了,这俩的位置还是这么令人迷惑,谜之设计啊。
1、按一次按键,就改变led一次状态:
以led的状态反映消抖成功,自己其实可以试下不消抖是什么现象的,更能直观的感受到消抖的好处。
#include <reg52.h>
#include <intrins.h> //有nop
sbit led=P2^7;
sbit k1=P3^1;
void Delay11ms() //@11.0592MHz,11毫秒
{
unsigned char i, j;
_nop_();
_nop_();
_nop_();
i = 119;
j = 82;
do
{
while (--j);
} while (--i);
}
void indpendent_key()
{
if(k1==0)
{
Delay11ms;
if(k1==0)
led=!led;
while(!k1); //检测按键是否松开
}
}
void main()
{
while(1)
{
independent_key();
}
}
2、用不同的独立按键对led进行不同的操作
K1左移led灯,K2右移led灯。
#include <reg52.h>
sbit k1=P3^1;
sbit k2=P3^0;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
unsigned char n;
void main()
{
P2=~0x01; //上电D1点亮
while(1)
{
if(k1==0)
{
Delay10ms;
while(k1==0);
Delay10ms;
n++; //n自增
if(n>=8) //限制n自增范围
n=0;
P2=~(0x01<<n); //led的第n+1位亮
}
if(k2==0)
{
Delay10ms;
while(k2==0);
Delay10ms;
if(n==0) //n减到0后变为7
n=7;
else //n未减到0,自减
n--;
P2=~(0x01<<n); //led的第n+1位点亮
}
}
}
K1增加一个led亮,K2减少一个led
#include <reg52.h>
sbit k1=P3^1;
sbit k2=P3^0;
void Delay10ms() //@11.0592MHz
{
unsigned char i, j;
i = 108;
j = 145;
do
{
while (--j);
} while (--i);
}
unsigned char n;
void main()
{
P2=0xfe; //上电D1点亮
while(1)
{
if(k1==0)
{
Delay10ms;
while(k1==0);
Delay10ms;
n++; //n自增
if(n>=8) //限制n自增范围
n=0;
P2=0xfe<<n; //led增加1位亮
}
if(k2==0)
{
Delay10ms;
while(k2==0);
Delay10ms;
if(n==0) //n减到0后变为7
n=7;
else //n未减到0,自减
n--;
P2=0xfe<<n; //led减少1位点亮
}
}
}
注意两端代码是有差别的哦,第二个代码搞不好还有的小BUG,不过上机能运行就是好代码!(手动滑稽,狗头保命)
萌新上路,制作不易,如有错误还请评论区指正。各位帅气逼人、美若天仙、颜值爆表的看官老爷点个赞吧,求求了。(在线卑微求赞)