51单片机-矩阵按键(清翔版)

51单片机-矩阵按键

矩阵键盘使用的是行和列的交叉点的形式来判断键盘按下的坐标。
在这里插入图片描述
)列坐标
在矩阵键盘中P3-4到P3-7为矩阵键盘的列坐标,当将列坐标引脚拉高以后(列坐标引脚给高电平,这时行坐标给低电平),当某一列有按键按下之后这一列整体就会被拉低。从而使用这种方法来判断按键那一列被按下。

P3 = 0xF0;
if(p3 != 0XF0){ //不等于 0XF0说明P3-4到P3-7中有一列的按键被按下
	dely(10);//延时消抖
  if(p3 != 0XF0){
  	switch(p3){
        case 0xe0: value = 0;break; //说明第一列被按下(1110 0000)
        case 0xd0: value = 1;break; //说明第2列被按下(1101 0000)
        case 0xb0: value = 2;break; //说明第3列被按下(1011 0000)
        case 0x70: value = 3;break; //说明第4列被按下(0111 0000)
    }
  }
}

(2)行坐标
行坐标也是使用同样的方法(行给高电平,列给低电平),当一行为低电平时,说明这一行中有一个按钮被按下

P3 = 0xof;//0000 1111
if(p3 != 0xof){ //不等于 0XF0说明P3-4到P3-7中有一列的按键被按下
	dely(10);//延时消抖
  if(p3 != 0xof){
  	switch(p3){
        case 0x0e: value = value;break; //说明第1行被按下(第一行被按下值不用改变,因为第一行就是从1-4进行排列,value的值在上面已经设置好了)
        case 0x0d: value = value + 4;break; //说明第2行被按下
        case 0x0b: value = value + 8;break; //说明第3行被按下
        case 0x07: value = value + 12;break; //说明第4行被按下
    }
  }
}

3)显示数据
当进行完成上面这两部,value就已经存放了矩阵键盘中的详细数据,矩阵键盘是一个4*4的所以可以用0-15来表示任何按键。

//0 - f 共阴极

char led[] = { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71} 

矩阵按键完整代码
注意:这里直接将行与列的按键读值放到了一起,是因为按键按下去的时候单片机运行速度很快,所以当按键按下去直接执列读列然后存入value,在读行再存入value。(value是做的加法)

void NumberKey(){
    P3 = 0xf0; //设置初始值,(行为低位,列为高位)
    if(P3 != 0xf0){
        dely(20);
        if(P3 != 0xf0){
            switch (P3) {
                case 0xe0: value = 0;break;
                case 0xd0: value = 1;break;
                case 0xb0: value = 2;break;
                case 0x70: value = 3;break;
            }
            //因为单片机速度很快,所以在按键按下的时候就可以直接执行下面的程序,也就是直接将行列读出来
            P3 = 0x0f; //将行赋予初始值
            switch (P3) {
                case 0x0e: value = value;break;
                case 0x0d: value = value + 4;break;
                case 0x0b: value = value + 8;break;
                case 0x07: value = value + 12;break;
            }
            while (P3 != 0x0f);//松手检测
        }
    }
}

(5)完整代码

#include "stdio.h"
#include "reg52.h"


#define uchar unsigned char
#define uint unsigned int

//数码管段选与位选
sbit duan = P2^6;
sbit wei = P2^7;

//建立全局变量,存放要显示的数码管字符数组中的位置
uint value = 0;

//16进制所有字符
uchar  led[] = {0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};

//延时函数
void dely( uint z ){
    uint x,y;
    for(x = z;x > 0;x--){
        for(y = 114; y > 0;y--);
    };
}

//数码管显示函数
void play(uint n){?¢
    //打开位选
    P0 = 0xFF;
    wei = 1;
    P0 = 0xFE;
    wei = 0;
    //打开段选
    duan = 1;
    P0 = led[n]; //显示按键具体数值
    duan = 0;
    dely(5);
}

void NumberKey(){
    P3 = 0xf0; //设置初始值,(行为低位,列为高位)
    if(P3 != 0xf0){
        dely(20);
        if(P3 != 0xf0){
            switch (P3) {
                case 0xe0: value = 0;break;
                case 0xd0: value = 1;break;
                case 0xb0: value = 2;break;
                case 0x70: value = 3;break;
            }
            //因为单片机速度很快,所以在按键按下的时候就可以直接执行下面的程序,也就是直接将行列读出来
            P3 = 0x0f; //将行赋予初始值
            switch (P3) {
                case 0x0e: value = value;break;
                case 0x0d: value = value + 4;break;
                case 0x0b: value = value + 8;break;
                case 0x07: value = value + 12;break;
            }
            while (P3 != 0x0f);//松手检测
        }
    }
}


void main(){
    while(1){
        NumberKey();
        play(value);
    }
}