一、原理
与独立按键不同的是,按键的两个引脚都分别连接的单片机的I/O端口,一个作为行信号,另外一个作为列信号。矩阵键盘的实现和动态数码管有一定的相似之处,动态数码管是循环通过段选来点亮。而矩阵键盘(4*4)是循环检测键值判断是否按下。
对于矩阵键盘,我们只能逐行扫描,然后读取列的状态信号。如果R3行输出低电平,那么黄色按键如果有按下动作的话,那读取C2列信号也应该为低电平,而该行上其他没有按下动作的按键的列信号则为高电平。因此,我们可以得到矩阵键盘的基本扫描步骤:
1、 R1输出低电平,R2、R3、R4输出高电平,逐个读取C1、C2、C3、C4判断列信号,如果都为高电平则R1行上没有按键按下。
2、 R2输出低电平,R1、R3、R4输出高电平,逐个读取C1、C2、C3、C4判断列信号。
3、 R3输出低电平,R1、R2、R4输出高电平,发现C2列信号为低电平,那么可以判断得R3行的C2列的按键有按下动作。
4、 R4输出低电平,R1、R3、R4输出高电平,逐个读取C1、C2、C3、C4判断列信号。
如此循环往复,扫描的按键的状态。
则我们写一个代码,使按下不同的按键,数码管显示不同的数字,如下图(显示红色的数字或字母):
二、代码:
#include "reg52.h"
sbit HC138_A = P2^5;
sbit HC138_B = P2^6;
sbit HC138_C = P2^7;
sfr P4 = 0xc0;//头文件中无P4,定义内存地址
sbit R1 = P3^0;
sbit R2 = P3^1;
sbit R3 = P3^2;
sbit R4 = P3^3;//行
sbit C1 = P4^4;
sbit C2 = P4^2;
sbit C3 = P3^5;
sbit C4 = P3^4;//列
unsigned char key_num;
unsigned char code SMG_duanma[18] = {
// 0 1 2 3 4 5 6 7
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
// 8 9 A B C D E F
0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
// - .
0xbf,0x7f}; //共阳数码管
void InitHC138(unsigned char n)//译码器电路,选Y
{
switch (n)
{
case 4://LED Y4
HC138_C = 1;
HC138_B = 0;
HC138_A = 0;
break;
case 5://蜂鸣器与继电器 Y5
HC138_C = 1;
HC138_B = 0;
HC138_A = 1;
break;
case 6://数码管位置 Y6
HC138_C = 1;
HC138_B = 1;
HC138_A = 0;
break;
case 7://数码管段码 Y7
HC138_C = 1;
HC138_B = 1;
HC138_A = 1;
break;
}
}
void SMG_KeyNum(unsigned char value)//数码管位置(只在第一位)、数据
{
InitHC138(6);
P0 = 0x01;
InitHC138(7);
P0 = value;
}
void ScanKeys()
{
//扫描第一行
R1 = 0; R2 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
while(!C1);//松开后
key_num = 0;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C2 == 0)
{
while(!C2);
key_num = 1;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C3 == 0)
{
while(!C3);
key_num = 2;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C4 == 0)
{
while(!C4);
key_num = 3;
SMG_KeyNum(SMG_duanma[key_num]);
}
//扫描第二行
R2 = 0; R1 = R3 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
while (!C1);
key_num = 4;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C2 == 0)
{
while(!C2);
key_num = 5;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C3 == 0)
{
while(!C3);
key_num = 6;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C4 == 0)
{
while(!C4);
key_num = 7;
SMG_KeyNum(SMG_duanma[key_num]);
}
//扫描第三行
R3 = 0; R1 = R2 = R4 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
while(!C1);
key_num = 8;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C2 == 0)
{
while(!C2);
key_num = 9;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C3 == 0)
{
while(!C3);
key_num = 10;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C4 == 0)
{
while(!C4);
key_num = 11;
SMG_KeyNum(SMG_duanma[key_num]);
}
//扫描第四行
R4 = 0; R1 = R2 = R3 = 1;
C1 = C2 = C3 = C4 = 1;
if (C1 == 0)
{
while(!C1);
key_num = 12;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C2 == 0)
{
while(!C2);
key_num = 13;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C3 == 0)
{
while(!C3);
key_num = 14;
SMG_KeyNum(SMG_duanma[key_num]);
}
else if (C4 == 0)
{
while(!C4);
key_num = 15;
SMG_KeyNum(SMG_duanma[key_num]);
}
}
void main()
{
while(1)
{
ScanKeys();
}
}
三、硬件结果