51单片机快速入门之矩阵按键2024/10/15

51单片机快速入门之矩阵按键

图片来源于网络:

原理其实很简单 坐标系理论

硬件链接

p10-p13都为高电平 1111

p14-p17都为低电平 0000

此时 p1=0x0f

当按钮按下之后 p1将不在=0x0f

检测程序开始执行,扫描是那个按钮被按下

根据上述图片假设按键 0 被按下

p1 != 0x0f 此时进入检测程序

p1=0x7f 0111 1111 此时 p1.7 为 低电平

由图可以看出当c d e f 任意一个键位按下,电路导通,

电路导通低电平之后,低电平的优先级通常是最高的

说以这里会导致p10-p14 io口接地

我们只需要检测此时 p1是否还=0x7f 即可知道该行按钮是否按下

这里我们按下的是按键 0 所以 继续往下检测

p1=0x bf 1011 1111 p1.6为低

p1=0x df 1101 1111 p1.5为低

p1=0x ef 1110 1111 p1.4为低

因按键0被按下 所以此时 p1.0 被拉低 p1此时=0xee 1110 1110

可以看出实际上我们是在检测p10-p13是否被拉低

因此我们可以用到

按位与 &

对于两个二进制数的每一位,按位与运算遵循以下规则:

  • 1 & 1 结果为 1
  • 1 & 0 结果为 0
  • 0 & 1 结果为 0
  • 0 & 0 结果为 0

由上述我们可以知道

当p1=0x7f p1=0x bf p1=0x df p1=0x ef

所以我们用按位与运算

tmp=0x7f;//设定一个中间变量

检测P1==tmp;

如果不等于执行下方取低四位操作

JC=P1 & 0xf //按位 与 运算 这个运算只取低四位,其他不关心

  1. 十六进制数 0x7F。在二进制中,0x7F 表示为 0111 1111

  2. JC = tmp & 0xF;tmp 和十六进制数 0xF(在二进制中表示为 0000 1111)执行按位与运算。按位与运算的规则是,只有当两个对应的二进制位都为1时,结果的对应位才为1,否则为0。因此,tmp & 0xF 的计算过程如下:

    0111 1111 (tmp)
    & 0000 1111 (0xF)

    0000 1111

所以,tmp & 0xF 的结果是 0000 1111,在十六进制中表示为 0x0F,在十进制中表示为 15

因按键0被按下 所以此时 p1.0 被拉低 p1此时=0xee 1110 1110

所以p1此时等于0xee

JC=P1 & 0xf

  1110 1110 (tmp) 
& 0000 1111 (0xF) 
---------- 
  0000 1110 

0000 1110,在十六进制中表示为 0x0E

参考十六进制映射表

每个十六进制数字对应四位二进制数字的映射如下:

0 -> 0000 
1 -> 0001 
2 -> 0010 
3 -> 0011 
4 -> 0100 
5 -> 0101 
6 -> 0110 
7 -> 0111 
8 -> 1000 
9 -> 1001 
A -> 1010 
B -> 1011 
C -> 1100 
D -> 1101 
E -> 1110 
F -> 1111 

结合上述我们可以写出如下完整程序

#include <STC89C5xRC.H>

unsigned char i,j,tmp;//设定变量
unsigned char BUTTON[]={0xef,0xdf,0xbf,0x7f} ;//p1.4 p1.5 p1.6 p1.7
unsigned char LOWJC[]={0xe,0xd,0xb,0x7}; //p1.0 p1.1 p1.2 p1.3 低四位
unsigned char btnum[4][3] = {
    {'0', '1', '2', '3'}, //第0行 p1.4
    {'4', '5', '6', '7'}, //第1行 p1.5
    {'8', '9', 'A', 'B'}, //第2行 p1.6
    {'C', 'D', 'E', 'F'}  //第3行 p1.7
}; 第0列,第1列,第2列,第3列
   p1.0   p1.1  p1.2  p1.3
void main(){


while(P1 !=0x0f ) //当按钮被按下,P1不等于初始状态 满足条件,执行检测程序
{
    for(i=0;i<4;i++)//从p1.7开始往下查
{

    if(P1 !=BUTTON[i]) //当检测到P1状态与表格中不相等时执行
        { tmp=P1 & 0xf; //取低四位,并获取 i 行
            for (j=0;j<4;j++)//通过后四位查表
                { if(tmp==LOWJC[j])
                        {    //满足条件获取列 j
                                输出 btnum[i][j];
                             //假设按键0被按下 i=0
                             //j=0           
                                btnum[0][0] 就会得到 字符 0                   
                                }

                            }

                    }

}

}

}

第二种办法,直接建立字符段码

我们知道1110 1110 时为按钮 0

1110 1101时为按钮1

建立表格:

unsigned char buttonCodes[] = { 
    0xEE, // 按钮 0 (1110 1110) 
    0xED, // 按钮 1 (1110 1101) 
    0xEB, // 按钮 2 (1110 1011) 
    0xE7, // 按钮 3 (1110 0111) 
    0xDE, // 按钮 4 (1101 1110) 
    0xDD, // 按钮 5 (1101 1101) 
    0xDB, // 按钮 6 (1101 1011) 
    0xD7, // 按钮 7 (1101 0111) 
    0xBE, // 按钮 8 (1011 1110) 
    0xBD, // 按钮 9 (1011 1101) 
    0xBB, // 按钮 A (1011 1011) 
    0xB7, // 按钮 B (1011 0111) 
    0x7E, // 按钮 C (0111 1110) 
    0x7D, // 按钮 D (0111 1101) 
    0x7B, // 按钮 E (0111 1011) 
    0x77  // 按钮 F (0111 0111)
}; 

剩下的就是进入检测 判断

for(i=0;i<16;i++)

{

if(P1== buttonCodes[I])

{输出 i 数字 }

}

相关推荐
sinat_360704825 小时前
STM32 看门狗
stm32·单片机·嵌入式硬件
亿道电子Emdoor5 小时前
【ARM】MDK如何生成指定大小的bin文件,并指定空区域的填充数据
arm开发·stm32·单片机
mftang6 小时前
STM32 CAN过滤器配置和应用方法介绍
stm32·单片机·嵌入式硬件
楼台的春风7 小时前
【详细讲解在STM32的UART通信中使用DMA机制】
stm32·单片机·嵌入式硬件·mcu·物联网·嵌入式·信息与通信
Chambor_mak8 小时前
stm32单片机个人学习笔记16(SPI通信协议)
stm32·单片机·学习
电子科技圈8 小时前
在低功耗MCU上实现人工智能和机器学习
人工智能·经验分享·科技·嵌入式硬件·mcu·物联网·机器学习
小白今天也很酷9 小时前
Python与MCU通信:串口数据采集及CSV/Excel存储方法
python·单片机·excel
海的预约9 小时前
51单片机-按键
单片机·嵌入式硬件·51单片机
qq_75568224020 小时前
STM32使用NRF2401进行数据传送
stm32·单片机·嵌入式硬件
FreakStudio1 天前
开源一款串口舵机驱动扩展板-FreakStudio多米诺系列
单片机·嵌入式·大学生·电子diy