首页 > 代码库 > 单片机独立按键与矩阵按键

单片机独立按键与矩阵按键

 

独立按键

首先既然是检测输入,对于当然要使能上拉电阻,来检测变化。因为除了P0口外,P2,P3,P4都是内置上拉电阻的双向IO口,作为输入前需要拉为高电平。 当有按键按下,致使单片机的某个引脚接地,变为低电平时,我们就认为这个按键按下了。当按键松开后,由于输入不会锁存,所以此时拉高的引脚回归到高电平。

 

 

独立按键的内部原理。

独立按键的4个引脚中,两两为一组。每一组的2个引脚是连在一起的,当按键按键时,2个组又连接了,也就是4个脚都连接一起了。

 技术分享

 

 

按键的很重要注意点就是消除抖动,消抖。因为人按下按键不是并瞬间到位的,按键在按下的过程中会有抖动。我们需要通过延时来让单片机绕过抖动的时间。

技术分享

 

 

下面是一个用按键作为开关间接控制LED的demo。

 

 

技术分享

 

/***************************************
按键按下,LED亮,松开,LED熄灭

**************************************/


#include<reg51.h>typedef unsigned int uint;typedef unsigned char uchar ;sbit button = P2^0; //按键输入引脚sbit led = P0^0; //LED控制输出引脚/***************************/void delay(uint t);uchar isKeyPressed(void);/***************************/void main(void){ button = 1; //P2 是 准 IO口,作为输入前要写1 led = 1; while(1) { if(isKeyPressed()) { led = 0; delay(100); led =1; } }}uchar isKeyPressed(void){ uchar isPressed = 0; //是否按下标志位 uchar c=50; if(button==0) //初次检测 { delay(5); //消抖延时 if(button==0) //再次验证 { isPressed = 1; while(isPressed==0 && c--) //如果不用c作为计数器,那么一直按着按键的话,程序就会一直在这里循环。是否要用c需要根据自己的要求。 ; } } return isPressed;}void delay(uint t){ uint i; uchar j; for(i=t;i>0;i--) for(j=110;j>0;j--) ;}

 

 

矩阵按键

矩阵按键的检测方式有多种,最常用的就是行列式扫描检测。原理和独立按键是一样的,只不过我们要扫描一组按键,找出那个被按下的而已。

对行列式扫描的分析。

 

加入我们按下了按键S6,现在来检测它。

用红色表示1高电平,蓝色表示0低电平。

先给键盘连接的GPIO口赋值为0XF0。

技术分享

 

 

电平反转。

 

技术分享

 

 

这样就可以判断定了按键的坐标。

 

 

demo的连线图。

 

技术分享

 

 

/******************************
将按键的编号显示到数码管上
*****************************/


#include<reg51.h>typedef unsigned int uint;typedef unsigned char uchar;typedef signed char schar;/*************************/void delay(uint t) ;void showDigit(uint num);schar martixKeyScan(void);/***************************/uchar code TABLE[10]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F} ;#define DUAN_XUAN P1 //数码管的段选#define KEYS_REC P2 //连接矩阵键盘sbit Add0 = P0^0; //译码器的A0 A1 A3,用来数码管的位选sbit Add1 = P0^1;sbit Add2 = P0^2;void main(void){ schar keyRe; uint number=0; while(1) { keyRe = martixKeyScan(); if(-1 != keyRe){ number = keyRe; } showDigit(number); }}void showDigit(uint num){ uchar count = 0; //根据输入数据的位数来开启数码管的位。 do { switch(count) { case 0:Add2 = 1;Add1 = 1;Add0 = 1;break; //送入位选,显示这个数的个位 case 1:Add2 = 1;Add1 = 1;Add0 = 0;break; //显示十位 case 2:Add2 = 1;Add1 = 0;Add0 = 1;break; case 3:Add2 = 1;Add1 = 0;Add0 = 0;break; case 4:Add2 = 0;Add1 = 1;Add0 = 1;break; case 5:Add2 = 0;Add1 = 1;Add0 = 0;break; case 6:Add2 = 0;Add1 = 0;Add0 = 1;break; case 7:Add2 = 0;Add1 = 0;Add0 = 0;break; } DUAN_XUAN = TABLE[num%10]; //送入段选 delay(5); DUAN_XUAN = 0 ; //关闭所有段,消影 count++; }while(num/=10);}/**********************矩阵按键检测。有按键按下,返回按键的编号,否则返回-1;***********************/schar martixKeyScan(void){ schar col,row; uchar c=50; //松手计数器 KEYS_REC = 0xF0 ; //让连接键盘的高4位为1 ,低4位为0 if(KEYS_REC != 0xF0) //初次检查到按下 { delay(5); //消抖延时 if(KEYS_REC != 0xF0) //真的被按下了 { switch(KEYS_REC) { case 0X70: row =1 ;break; // 0111 0000 case 0XB0: row = 2; break; // 1011 0000 case 0XD0: row = 3;break; // 1101 0000 case 0XE0: row = 4;break; // 1110 0000 default:break; } KEYS_REC = 0x0F; //电平反转,检测列 switch(KEYS_REC) { case 0X07: col = 1;break; //0000 0111 case 0X0B: col = 2; break; //0000 1011 case 0X0D: col = 3;break; //0000 1101 case 0X0E: col = 4;break; //0000 1110 default:break; } while((c--) && (KEYS_REC!=0x0F)) //等待按键松手 { delay(5); } return (row-1)*4+col; //使用4X4的键盘 } //真的按下了 else return -1; } return -1;}void delay(uint t){ uint i,j; for(i=t;i>0;i--) for(j=123;j>0;j--) ;}

 

 

技术分享

 

单片机独立按键与矩阵按键