版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_17017545/article/details/81349250
扫描方法
1)逐行逐列扫描法(K6被按下)
比如说现在 K6 按下,那怎么知道哪个按下了呢?
首先第0行输出低电平0,其他行输出高电平1,所有列输出高电平,此时发现每一列的引脚仍然为高,说明第0行没有被按下。然后第1行输出低电平0,其他行输出高电平1,所有列输出高电平,发现第2列变成了低电平。可知第1行第2列有按键按下。(K6)
2)行列反转法(K6被按下)
首先让第0行,第1行,第2行,第3行,一次性输出0,0,0,0,而第0列,第1列,第2列,第3列跟51单片机相连的引脚全部拉高(1),之后读取第0列,第1列,第2列,第3列的电平,得到的是列的编码(1,1,0,1);然后第0列,第1列,第2列,第3列全置0,把行全部置1,再来判断行的编码(1,0,1,1),整个编码为:1101 1011,我们可以将它设计对应为K6(第1行第2列),从而得出是哪个按键被按下.
电路图
代码
******************************************************************/
* 【课程15】 ****矩阵按键的读取***********
* 【说 明】 ****采用逐列扫描法(没做松开按键的处理,后面介绍)
* 【描 述】 ****扫描一个按键按下,做键值处理,并通过数码管显示出来
******************************************************************/
#include<reg51.h> //51头文件,
//---------常用的两个宏定义--------------
#define uint8 unsigned char
#define uint16 unsigned int
//--------定义全局变量-------------------
uint8 Temp,Key_value;
//------------数码管段选显示数据-------------------
uint8 SEG_Data[16]={~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,
~0x07,~0x7F,~0x6F,~0x77,~0x7C,~0x39,~0x5E,~0x79,~0x71};
//------------函数的声明-----------------
void DelayMS(uint16 dly);
void Key_Scan1(void); //扫描按键方法1
void Key_Scan2(void); //扫描按键方法2
void Key_Down(void); //判断是否有按键被按下
//-------------主函数--------------------
void main(void)
{
while(1)
{
Key_Down();
}
}
/********************************************************
** 名称 :void Key_Down(void)
** 功能 :判断是否有按键被按下
** 入口参数 :无
** 出口参数 :无
*********************************************************/
void Key_Down(void)
{
P2 = 0xf0; //设置I/O的输入输出
Temp = P2;
Temp = Temp&0xf0;
if(Temp!=0xf0) //只要有按键按下Temp就不等于0xf0
{
DelayMS(100); //软件延时去抖
if(Temp!=0xf0) //再次判断是否仍处于按下状态
{
// Key_Scan1(); //按键扫描方法一
Key_Scan2(); //按键扫描方法二
}
}
}
/********************************************************
** 名称 :void Key_Scan1(void)
** 功能 :扫描按键方法一
** 入口参数 :无
** 出口参数 :无
*********************************************************/
void Key_Scan1(void)
{
P2 = 0xfe;
Temp = P2;
switch(Temp)
{
case 0xee: Key_value=0;
break;
case 0xde: Key_value=1;
break;
case 0xbe: Key_value=2;
break;
case 0x7e: Key_value=3;
break;
}
P2 = 0xfd;
Temp = P2;
switch(Temp)
{
case 0xed: Key_value=4;
break;
case 0xdd: Key_value=5;
break;
case 0xbd: Key_value=6;
break;
case 0x7d: Key_value=7;
break;
}
P2 = 0xfb;
Temp = P2;
switch(Temp)
{
case 0xeb: Key_value=8;
break;
case 0xdb: Key_value=9;
break;
case 0xbb: Key_value=10;
break;
case 0x7b: Key_value=11;
break;
}
P2 = 0xf7;
Temp = P2;
switch(Temp)
{
case 0xe7: Key_value=12;
break;
case 0xd7: Key_value=13;
break;
case 0xb7: Key_value=14;
break;
case 0x77: Key_value=15;
break;
}
P1 = SEG_Data[Key_value];
}
/********************************************************
** 名称 :void Key_Scan2(void)
** 功能 :扫描按键方法二
** 入口参数 :无
** 出口参数 :无
*********************************************************/
void Key_Scan2(void)
{
uint8 key_row,key_col,key;
key_col = P2; //以第一个按键为例 (11101110)
key_col = key_col & 0xf0; //11100000
key_col = key_col |0x0f; //11101111
P2 = key_col; //11101111
key_row = P2; //11101110
// key_row = key_row & 0x0f; //00001110
// key_col = key_col & 0xf0; //11100000
// key = key_row + key_col; //11101110
key = key_row;
switch(key)
{
case 0xee: Key_value=0;
break;
case 0xde: Key_value=4;
break;
case 0xbe: Key_value=8;
break;
case 0x7e: Key_value=12;
break;
case 0xed: Key_value=1;
break;
case 0xdd: Key_value=5;
break;
case 0xbd: Key_value=9;
break;
case 0x7d: Key_value=13;
break;
case 0xeb: Key_value=2;
break;
case 0xdb: Key_value=6;
break;
case 0xbb: Key_value=10;
break;
case 0x7b: Key_value=14;
break;
case 0xe7: Key_value=3;
break;
case 0xd7: Key_value=7;
break;
case 0xb7: Key_value=11;
break;
case 0x77: Key_value=15;
break;
}
P1 = SEG_Data[Key_value];
}
/********************************************************
** 名称 :void DelayMS(uint16 dly)
** 功能 :毫秒级延时(24M的晶振)
** 入口参数 :dly 用户的延时参数
** 出口参数 :无
*********************************************************/
void DelayMS(uint16 dly)
{
uint16 x,y;
for(x=dly;x>0;x--)
for(y=247;y>0;y--);
}