小白上路之51单片机(STC89C52)--按键


按键介绍

实物图 VS 原理图:
在这里插入图片描述

独立按键

独立按键原理

在这里插入图片描述
  四个按键的一端全部供地。默认状态下(按键未按下时),按键的各个管脚并非完全导通(参见按键原理图);按下按键后,相应的单片机端口都会被拉低(因为P3口是准双向IO口)。
  如下图,为准双向IO结构图:
准双向IO结构图
  由上图可得,NPN三极管发射极接地,基极连着非门,集电极连接着一个上拉电阻R,这便是其内部结构图。
  而单片机IO口则是从集电极引出:当按键按下,低电平就会通过IO口,通过内部输入,进入单片机使其拉低;默认情况下(即按键未被按下,IO口默认为高电平),通过外部的4.7K的上拉电阻,输出高电平,即使没有该外部的上拉电阻,也仍为高电平,因为其内部有上拉电阻接在VCC上。
  注:P1、P2、P3口都是准双向IO口,即内部都具有上拉电阻,而P0口是漏极开路,内部无上拉,直接通过集电极接到单片机IO口。因此P0口全部都要加上拉,而P1、P2、P3口加上拉是为了提高单片机IO口的驱动能力。
分析一下如何输出高低电平:
1.针对P1、P2、P3口,即内部有上拉。

  假设内部输出为1,通过非门后变为0,此时三极管不会导通(发射极接地也为低电平,无电压差),由于内部有上拉,则电源从VCC出来,到IO口会输出高电平。即内部输出为高电平,IO口输出也为高电平。
  假设内部输出为0,通过非门后则为1,此时三极管导通(发射极与集电极连通),由于发射极接地,故输出为低电平。即内部输出为低电平,这=则IO口输出也为低电平。

2.针对P0口,即内部无上拉。
  假设内部输出为1,通过非门后变为0,同理三极管不会导通,由于内部无上拉,则IO口无法输出,若要让其输出,则需要在外部加上一个上拉电阻,此时才会输出一个高电平。内部输出为0则同理。

下面来说一说关于按键抖动现象。
  按键在闭合和断开时,触电会存在抖动现象——一般可通过软件消抖的方法解决即延时后再次判断按键是否按下。(也可通过硬件电路消抖)

在这里插入图片描述

源程序–独立按键

按下按键K1,点亮led1,再次按下,led1被熄灭。

#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;

sbit L1=P2^0;
sbit K1=P3^1;

void delay(u16 i)
{
	while(i--);
}
void keypros()
{
	if(K1==0)
	{
		delay(1000);//延时 待其稳定
		if(K1==0)//按键消抖
		{
			L1=~L1;//状态翻转
		}
	}
	while(!K1);//判断按键是否已经松开:按键松开时,P31管脚是默认为高电平,即退出while循环代表确实已经松开;若此时为抖动,则满足while循环,直到按键松开
}
void main()
{
	while(1)
	{
		keypros();
	}
}

矩阵按键

矩阵按键的由来

在这里插入图片描述

  实际上就是将独立按键重新组合,将独立按键每行按键的一个管脚连接在一起,引出一条控制线,对于每列来说,则把该列按键剩下的管脚连接到一起,引出一条控制线,最后组成独立按键。

矩阵按键扫描原理

法一:逐行扫描

  通过高四位(即P17、P16、P16、P15:接的是矩阵按键的每一行而引出的管脚)轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1时,则说明有按键按下,而后通过接收到的数据中哪位为0来判断时哪个按键被按下。

eg:P17-P15轮流输出低电平,若此时S14按键被按下,则S14的P14口由于轮流输入低电平而被拉低,随着按键按下,低电平会流入到另一管脚P12口,即P12口会输出低电平。

法二:行列扫描(通常采用)
  通过高四位全部输出低电平,低四位输出高电平。当接收到的数据其低四位不全为高电平时,则说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下;而后再反过来,高四位输出高电平,低四位输出低电平,根据接收到的高四位的值判断是哪一行有按键按下,如此便可确定是哪一个按键按下了。

eg:

  1. 先让高四位全部输出低电平,低四位全部输出高电平:若此时S10按键被按下,则其对应的P12口会变为低电平,则此时低四位并非全为1,即可确定是哪一列有按键被按下;
  2. 而后再将高四位与低四位的初始电平翻转,由于S10按键被按下,则此时P15口会导通变为低电平,于是此时的高四位并非全为高电平,即可确定是哪一行有按键被按下。

源程序–矩阵按键

#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;

#define GPIO_KEY P1
#define GPIO_DIG P0

sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;

u8 keyvalue;
u8 code smgduan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

void delay(u16 i)
{
	while(i--);
}
void Keydown()
{
	u8 a=0;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f)
	{
		delay(1000);
		if(GPIO_KEY!=0x0f)
		{
			GPIO_KEY=0x0f;
			switch(GPIO_KEY)
			{
				case 0x07:keyvalue=0;break;//0000 0111
				case 0x0b:keyvalue=1;break;//0000 1011
				case 0x0d:keyvalue=2;break;//0000 1101
				case 0x0e:keyvalue=3;break;//0000 1110
			}
			GPIO_KEY=0xf0;
			switch(GPIO_KEY)
			{
				case 0x70:keyvalue=keyvalue;break;//0111 0000
				case 0xb0:keyvalue=keyvalue+4;break;//1011 0000
				case 0xd0:keyvalue=keyvalue+8;break;//1101 0000
				case 0xe0:keyvalue=keyvalue+12;break;//1110 0000
			}
			while((a<50)&&(GPIO_KEY!=0xf0))//按键松开判断以及超时退出
			{
				delay(1000);
				a++;
			}
		}
	}
}
void main()
{
	LSA=0;LSB=0;LSC=0;
	while(1)
	{
		Keydown();
		GPIO_DIG=smgduan[keyvalue];
	}
}
  • 4
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值