51单片机入门之按键检测

书接上回讲了LED的引脚,现在来分享按键模块

下面是按键模块及其原理图

按键其实就是一个会回弹的振片,通过内部设计使得按键按下时,电路被接通(不再是断路的状态),电路中的电流从无到有,电平发生变化,观察原理图发现按键一端接GND一端接P3口,GND其实就是接地,也就是低电平,P3口默认接的是高电平,而按键如果按下,对于一个导通的线(例如图中的绿色线)来说,P3_1的电平就会跟GND一样,也就是低电平,而这种变化被单片机捕捉到,从而检测到按键按下的操作。这就是检测按键按下的基本原理。


了解了基本原理,来看代码如何实现检测按键按下(补充:~是逻辑电路中的非门,其实就是电平状态取反,比如P2_1=1;    ~P2_1后   P2_1=0;)

#include <REGX52.H>

void main()
{
	while(1)
	{
		if(P3_1==0)//P3_1是第一个按键的引脚,用于检测第一个按键的按下与否,
                   //P3口引脚开始是默认为高电平,按下按键使电路导通后,
                   //P3口就接地(GND)也就是变成低电平。1表示高电平,0表示低电平
		{
			P2_0=0;//如果按下第一个按键就让第一个LED点亮
		}
		else
		{
			P2_0=1;//按键重新变为断开状态则第一个LED熄灭
		}
	}
}

在单片机上运行代码发现不足之处是我要一直按着按键才能使LED一直亮,但是一松手,LED就熄灭了。想着能不能实现按下一次后LED就一直亮,再按下一次LED就熄灭。这就运用到while循环的一个巧妙思想。

#include <REGX52.H>

void main()
{
    while(1)
    {
        if(P3_1==0)//如果按键1按下
        {
            while(P3_1==0);   //这要手指还在按着按键,就再循环里一直不出来,手指松开,则跳出循环 
                              //执行LED的命令
            P2_0=~P2_0;       //手指松开,使LED1口的电平反转,达到按下一次,小灯亮灭情况变化一次
        }
        //思考可知按键此时是松手那一刻跳出while循环才点亮LED1。即松手点亮。由于已经松手,P3_1==1,不满足if判断条件,也就不能进入if的执行语句,LED1刚刚被翻转的电平一直不变,也就能实现不用一直按着按键也能让灯一直亮着了。
    }
}        //如果再按下一次按键,就再进入if语句里,把电平再翻转一次。由亮,变为不亮。

编译烧录后发现现象还是有点小故障,其实是因为弹片在按下和弹起的时候都会有微小的振动,振动时间很段,就几毫秒的时间,但是对于单片机这样高速运行的CUP来说振动的时间并不是极短的,抖动造成的电平变化是不可以被忽略的。

振动时也会引起电平变化,我们为了振动的电平变化不被检测到,我们就用一个延时函数delay,让CPU去执行delay函数而忽略弹片的振动,我们把这样的行为叫消抖

#include <REGX52.H>

void Delay(unsigned int xms)//延时函数
{
	unsigned char i, j;
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void main()
{
	while(1)
	{
		if(P3_1==0)			//如果K1按键按下
		{
			Delay(20);		//传入参数,知道到底要延时多少毫秒,由于按键抖动一般在10ms左右,延 
                            //时20毫秒就够了。目的是为了消按键按下的抖动。

			while(P3_1==0);	//松手检测
			Delay(20);		//目的是为了消按键弹起的抖动
			
			P2_0=~P2_0;		//翻转LED的亮灭情况。
		}
	}
}

总结前面学到的东西:1:按下按键,导通电路,P3口变为低电平。   2:松手点亮 while循环 。 3:按键消抖 delay函数延时。

接下来尝试用学到的知识完成单片机上与按键有关的小题目


题目1:按下按键1实现让LED的8个灯,从左往右的流水。按下按键2实现LED全部熄灭的效果,按键3实现让LED流水灯延时时间增加。按键4实现让LED流水灯从右往左的流水。

#include <REGX52.H>

sbit key1 = P3^1;  //仔细查看原理图的引脚定义,发现按键1是P3_1引脚,发现按键2是P3_0引脚,并没有 
                   //按0123的顺序来。
sbit key2 = P3^0;  
sbit key3 = P3^2;  
sbit key4 = P3^3;  

unsigned int time = 100;
void delay(unsigned int t) {
    unsigned int i, j;
    for(i = t; i > 0; i--)
        for(j = 110; j > 0; j--);  
}

void main() {
	  int i=0;
    unsigned char code Led_mod[]={0XFE,0XFD,0XFB,0XF7,0XEF,0XDF,0XBF,0X7F,0XFF};//从1111 
    1110开始

    while(1) 
	  {
        if(key1 == 0) //如果按键1按下
				{  
            for(i=0;i<8;i++) //循环数组得到流水灯
					   {
						   P2=Led_mod[i];
						   delay(200);
				     }
        }
				
        if(key2 == 0)       //如果按键2按下
				{  
            P2 = 0xFF;      //由于是低电平使能,故全灭就是1111 1111
        }
				
        if(key3 == 0)       //如果按键3按下
				{  
            time += 50;     //延时时间增加
            if (time > 500) //延时时间最大不能超过500
						{time = 500;} 
					  for(i=0;i<8;i++) //循环遍历数组得到流水灯
					   {
						     P2=Led_mod[i];
						     delay(time);  //延时函数使传入time变量而不是直接传入一个值
				     }
				}
				
        if(key4 == 0)        //如果按键4按下
				 {  
            for(i=8;i>=0;i--)  //从右往左的流水灯
					   {
						    P2=Led_mod[i]; 
						    delay(200);
				     }
        }
   }
}

等后续学习到中断函数就可以优化此题目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值