https://blog.csdn.net/qq_38351824/article/details/89135034
分类
编码键盘:闭合键的识别有专门的硬件编码器来实现,以此产生编码号和键值;
非编码键盘:靠软件编程来识别的键盘,在单片机里用的较多,分为独立键盘和矩阵式键盘
按下:接通电平
按下和松开时会存在抖动现象,默认按下很多次,因此要消抖。
消抖原理:延时函数,把抖动时间(大约5ms)消除掉
独立按键控制led,四个按键控制亮灭**
#include "reg51.h"
typedef unsigned char u8;
typedef unsigned char u16;
sbit led=P2^0; //led,P1口
sbit k1=P3^1; //按键的口
sbit k2=P3^0; //按键的口
sbit k3=P3^2; //按键的口
sbit k4=P3^3; //按键的口
void delay(u16 i)
{
while (i--);
}
void keypros()
{
if(k1==0) //判断是否低电平
{
delay(1000);//延时10ms消抖处理,利用延时把抖动的信号屏蔽掉
if(k1==0) //稳定闭合阶段的低电平,判断是否按下
{
led=~led; //状态反转
}
while(!k1); //松开的判断,松开电位为1,非运算跳出循环,往下进行
}
else if(k2==0)
{
delay(1000);
if(k2==0)
{
led=~led;
}
while(!k2);
}
else if(k3==0)
{
delay(1000);
if(k3==0)
{
led=~led;
}
while(!k3);
}
else if(k4==0)
{
delay(1000);
if(k4==0)
{
led=~led;
}
while(!k4);
}
}
void main()
{
led=1;
while(1)
{
keypros();
}
}
矩阵按键原理
由来:排成四行的独立按键,横向公用一条线,纵向公用另一条线。独立键盘与单片机连接时,每一个按键都需要单片机的一个I/O口,若某单片机系统需较多按键,如果用独立按键便会占用过多的I/O口资源。单片机系统中I/O口资源往往比较宝贵,当用到多个按键时,为了节省I/O口线,我们引入矩阵键盘。
检测时,先送一列为低电平,其余几列全为高电平(此时我们确定了列数),然后立即轮流检测一次各行是否有低电平,若检测到某一行为低电平(这时我们又确定了行数),则我们便可确认当前被按下的键是哪一行哪一列的,用同样方法轮流送各列一次低电平,再轮流检测一次各行是否变为低电平,这样即可检测完所有的按键,当有键被按下时便可判断出按下的键是哪一个键。当然我们也可以将行线置低电平,扫描列是否有低电平。这就是矩阵键盘检测的原理和方法。
#include "reg52.h"
#include "intrins.h"
typedef unsigned char u8;
typedef unsigned char u16;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
#define GPIO_KEY P1
#define GPIO_DIG P0 //定义按键端口
u8 KeyValue,a;
u8 code smgduan[]={0x3f , 0x06 , 0x5b , 0x4f , 0x66 , 0x6d ,0x7d , 0x07 , 0x7f , 0x6f , 0x77 , 0x7c ,
0x39 , 0x5e , 0x79 , 0x71 , 0x00};
void delay(u16 i)
{
while(i--);
}
void KeyDown() //扫描程序,行列扫描
{
GPIO_KEY=0x0f; //初始化为低电平
if(GPIO_KEY!=0x0f)
{
delay(1000); //延时消抖
if(GPIO_KEY!=0x0f)
{
GPIO_KEY=0x0f;
switch(GPIO_KEY) //高四位0,低四位1扫描,测试列
{
case 0x07: KeyValue=0; break; //0000 0111转16进制,表示第一个列按下
case 0x0b: KeyValue=1; break; //数码管显示1
case 0x0d: KeyValue=2; break;
case 0x0e: KeyValue=3; break;
}
GPIO_KEY=0xf0;
switch(GPIO_KEY) //低四位0,高四位1扫描,测试行,电平反过来
{
case 0x70: KeyValue=KeyValue; break; //0111 0000转16进制,表示第一个行按下,电平是反的
case 0xb0: KeyValue=KeyValue+4; break; //数码管显示5,此时keyvalue是行的返回值
case 0xd0: KeyValue=KeyValue+8; break;
case 0xe0: KeyValue=KeyValue+12; break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //检测是否按下
{
delay(1000);
a++; //a到50退出循环,防止一直按着消抖占用cpu
}
}
}
}
void main()
{
LSA=0;
LSB=0;
LSC=0; //数码管位选
while(1) //一直检测按键
{
KeyDown();//判断按键按下后
GPIO_DIG=smgduan[KeyValue]; //调用按键数码显示函数
}
}
**