51单片机矩阵按键是一种在单片机应用系统中广泛使用的按键排列方式,特别适用于需要多个按键但I/O口资源有限的情况。以下是对51单片机矩阵按键的详细介绍:
一、矩阵按键的基本概念
- 定义:矩阵按键,又称行列键盘,是用多条行线和列线交叉组成的键盘。在行线和列线的每个交叉点上设置一个按键,从而实现用较少的I/O口控制多个按键。
- 优势:矩阵按键能够有效地提高单片机系统中I/O口的利用率。例如,一个4x4的矩阵键盘只需8个I/O口就可以实现16个按键的功能。
二、矩阵按键的工作原理
- 行列扫描法:这是最常用的矩阵按键检测方法。首先,单片机通过程序控制将某一列线置为低电平,其余列线置为高电平,然后检测各行线是否有低电平信号。如果有,说明该行线与置为低电平的列线交叉点上的按键被按下。接着,轮流将各列线置为低电平,并检测各行线,直到找出被按下的按键。
- 线翻转法:另一种检测方法是线翻转法。首先,将所有行线置为低电平,检测所有列线是否有低电平信号。如果有,记录列线值。然后,将所有列线置为低电平,检测所有行线的值。由于有按键按下,行线的值也会有变化,记录行线的值。通过这种方法,可以检测到所有被按下的按键。
三、矩阵按键的编程实现
- 初始化:在程序中,首先需要初始化与矩阵键盘连接的I/O口,设置它们的初始状态。
- 扫描与检测:然后,通过循环或中断的方式不断扫描矩阵键盘。在扫描过程中,根据行列扫描法或线翻转法的原理,检测按键是否被按下。
- 消抖处理:由于机械按键在按下和松开时会产生抖动,因此需要在程序中加入消抖处理。常用的消抖方法有软件消抖和硬件消抖。在单片机应用中,软件消抖更为常见。
- 按键功能实现:当检测到按键被按下时,根据按键的位置执行相应的功能。例如,在计算器程序中,按键的位置可能对应不同的数字或运算符。
四、矩阵按键的应用实例
- 计算器:矩阵按键常用于计算器的键盘设计。通过4x4或更大规模的矩阵键盘,可以实现数字输入、运算符选择和功能键等操作。
- 电子密码锁:在电子密码锁中,矩阵按键用于输入密码。用户可以通过按下矩阵键盘上的按键来输入数字或字母密码。
- 游戏控制器:在一些简单的游戏控制器中,矩阵按键也常被用于实现方向键、功能键等操作。
当我们按下某一个按键时,该按键对应的那一行和那一列的引脚为0,其他的引脚为1
硬件原理图
代码实现
分别检测
#include "Int_MatrixKey.h"
#include <STC89C5xRC.H>
u8 Int_MatrixKey_CheckKey()
{
// P24 P25 P26 P27
// P20 +---+---+---+
// P21 +---+---+---+
// P22 +---+---+---+
// P23 +---+---+---+
// 扫描第一行,将P20置0,其余置1;P27-P20依次为:1111 1110
P2 = 0xFE;
// 检测第SW5是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1110
if (P2 == 0xEE) {
Delay1ms(10);
if (P2 == 0xEE) {
while (P2 == 0xEE);
return 5;
}
}
// 检测第SW6是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1110
if (P2 == 0xDE) {
Delay1ms(10);
if (P2 == 0xDE) {
while (P2 == 0xDE);
return 6;
}
}
// 检测第SW7是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1110
if (P2 == 0xBE) {
Delay1ms(10);
if (P2 == 0xBE) {
while (P2 == 0xBE);
return 7;
}
}
// 检测第SW8是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1110
if (P2 == 0x7E) {
Delay1ms(10);
if (P2 == 0x7E) {
while (P2 == 0x7E);
return 8;
}
}
// 扫描第二行,将P22置0,其余置1;P27-P20依次为:1111 1101
P2 = 0xFD;
// 检测第SW9是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1101
if (P2 == 0xED) {
Delay1ms(10);
if (P2 == 0xED) {
while (P2 == 0xED);
return 9;
}
}
// 检测第SW10是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1101
if (P2 == 0xDD) {
Delay1ms(10);
if (P2 == 0xDD) {
while (P2 == 0xDD);
return 10;
}
}
// 检测第SW11是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1101
if (P2 == 0xBD) {
Delay1ms(10);
if (P2 == 0xBD) {
while (P2 == 0xBD);
return 11;
}
}
// 检测第SW12是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1101
if (P2 == 0x7D) {
Delay1ms(10);
if (P2 == 0x7D) {
while (P2 == 0x7D);
return 12;
}
}
// 扫描第三行,将P22置0,其余置1;P27-P20依次为:1111 1011
P2 = 0xFB;
// 检测第SW13是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 1011
if (P2 == 0xEB) {
Delay1ms(10);
if (P2 == 0xEB) {
while (P2 == 0xEB);
return 13;
}
}
// 检测第SW14是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 1011
if (P2 == 0xDB) {
Delay1ms(10);
if (P2 == 0xDB) {
while (P2 == 0xDB);
return 14;
}
}
// 检测第SW15是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 1011
if (P2 == 0xBB) {
Delay1ms(10);
if (P2 == 0xBB) {
while (P2 == 0xBB);
return 15;
}
}
// 检测第SW16是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 1011
if (P2 == 0x7B) {
Delay1ms(10);
if (P2 == 0x7B) {
while (P2 == 0x7B);
return 16;
}
}
// 扫描第四行,将P23置0,其余置1;P27-P20依次为:1111 0111
P2 = 0xF7;
// 检测第SW17是否被按下,若被按下,P24会被拉低,P27-P20依次为:1110 0111
if (P2 == 0xE7) {
Delay1ms(10);
if (P2 == 0xE7) {
while (P2 == 0xE7);
return 17;
}
}
// 检测第SW18是否被按下,若被按下,P25会被拉低,P27-P20依次为:1101 0111
if (P2 == 0xD7) {
Delay1ms(10);
if (P2 == 0xD7) {
while (P2 == 0xD7);
return 18;
}
}
// 检测第SW19是否被按下,若被按下,P26会被拉低,P27-P20依次为:1011 0111
if (P2 == 0xB7) {
Delay1ms(10);
if (P2 == 0xB7) {
while (P2 == 0xB7);
return 18;
}
}
// 检测第SW20是否被按下,若被按下,P28会被拉低,P27-P20依次为:0111 0111
if (P2 == 0x77) {
Delay1ms(10);
if (P2 == 0x77) {
while (P2 == 0x77);
return 20;
}
}
return 0;
}
循环方式
u8 Int_KeyMatrix_CheckKey()
{
u8 i, j;
u8 lines[4] = {0xFE, 0xFD, 0xFB, 0xF7};
u8 columns[4] = {0x10, 0x20, 0x40, 0x80};
for (i = 0; i < 4; i++) {
P2 = lines[i];
for (j = 0; j < 4; j++) {
if ((P2 & columns[j]) == 0x00) {
Com_Util_Delay1ms(10);
if ((P2 & columns[j]) == 0x00) {
while ((P2 & columns[j]) == 0x00);
return 5 + j + 4 * i;
}
}
}
}
return 0;
}
通过这个函数就可以获取到每个矩阵对应的数字了
int main(){
u8 key;
while(1){
key = Int_KeyMatrix_CheckKey();
if(key){
//对应逻辑
}
}
}