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; //数码管显示1case 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]; //调用按键数码显示函数}}
**
