Contents
1> 硬件设计
1.1> 实物(4X4矩阵)
1.2> 原理图
1.3> PCB
轻触按键内部结构:
2> 行列反转扫描原理
2.1> 目的
4X4键盘中按下任意按键,都能识别;
2.2> 步骤1: 确定按键X(坐标)坐标
写端口:P2 = 0x 0F,
读端口P2值, 假如【K00】按下, 则P2.0电平拉低,读取值为 0x0E(0b 0000 1110)
- 编写代码测试:
#include <reg52.h>
/* byte device */
#define LED_PORT P0
#define KEY_PORT P2
int main(void)
{
while (1) {
KEY_PORT = 0x0F;
LED_PORT = KEY_PORT;
}
}
通过测试,
【K00】~ 【K03】按下时,D1灯亮; // KEY_PORT == 0x0E;
【K10】 ~【K13】按下时,D2灯亮; // KEY_PORT == 0x0D;
【K20】~ 【K23】按下时,D3灯亮; // KEY_PORT == 0x0B;
【K30】~ 【K33】按下时,D4灯亮 // KEY_PORT == 0x07;
得出结论:
通过对KEY_PORT 写0x0F,和读,能确定按键的X(行)坐标;
2.3> 步骤2: 确定按键Y(坐标)坐标
写端口:P2 = 0xF0;
读端口P2值, 假如【K00】按下, 则P2.0电平拉低,读取值为 0xE0(0b 1110 0000);
- 编写代码测试
#include <reg52.h>
/* byte device */
#define LED_PORT P0
#define KEY_PORT P2
int main(void)
{
while (1) {
KEY_PORT = 0xF0;
LED_PORT = KEY_PORT;
}
}
【K00】~ 【K30】按下时,D5灯亮; // KEY_PORT == 0xE0;
【K01】 ~【K31】按下时,D6灯亮; // KEY_PORT == 0xD0;
【K02】~ 【K32】按下时,D7灯亮; // KEY_PORT == 0xB0;
【K03】~ 【K33】按下时,D8灯亮 // KEY_PORT == 0x70;
对KEY_PORT 写0xF0, 读值,能确定key的Y(列)坐标;
2.4> 步骤3: 根据按键(X,Y)坐标,给按键编码(0~F);
【K00】:X坐标(0x0E), Y坐标(0xE0);0 + 0 = 0
【K01】:X坐标(0x0E), Y坐标(0xD0);1 + 0 = 1
【K02】:X坐标(0x0E), Y坐标(0xB0);2 + 0 = 2
【K03】:X坐标(0x0E), Y坐标(0x70);3 + 0 = 3
【K10】:X坐标(0x0D), Y坐标(0xE0);0+4 = 4
【K11】:X坐标(0x0D), Y坐标(0xD0);1+4 = 5
【K12】:X坐标(0x0D), Y坐标(0xB0);2+ 4 = 6
【K13】:X坐标(0x0D), Y坐标(0x70);3+4 = 7
【K20】:X坐标(0x0B), Y坐标(0xE0);0+8 = 8
【K21】:X坐标(0x0B), Y坐标(0xD0);1+8 = 9
【K22】:X坐标(0x0B), Y坐标(0xB0);2+ 8 = 10 (A)
【K23】:X坐标(0x0B), Y坐标(0x70);3+ 8 = 11 (B)
【K30】:X坐标(0x07), Y坐标(0xE0);0+12 = 12 (C)
【K31】:X坐标(0x07), Y坐标(0xD0);1+ 12 = 13 (D)
【K32】:X坐标(0x07), Y坐标(0xB0);2+12 = 14 (E)
【K33】:X坐标(0x07), Y坐标(0x70);3+ 12 = 15 (F)
有什么规律?X坐标,与Y坐标,按位或运算
X坐标: ---------- Y坐标
0x0E == 0; ------0xE0 == 0
0x0D == 4; ------0xD0 == 1
0x0B == 8; ------0xB0 == 2
0x07 == 12; ------0x70 == 3
3> 程序设计
- 设计要求:
- 给按键编码0~F,并在数码管上显示;
#include <reg52.h>
typedef unsigned char uchar8_t;
typedef unsigned short ushort16_t;
/* byte device */
#define NUM_PORT P0
#define KEY_PORT P2
/*0~F, off*/
unsigned char DS_code[17] = {0xC0, 0xF9, 0xA4, 0xB0, 0x99,
0x92, 0x82, 0xF8, 0x80, 0x90,
0x88, 0x83, 0xa7, 0xa1, 0x86,
0x8E, 0xFF };
void digit_ctrl(uchar8_t num);
uchar8_t key_scan(void);
/**
* main
*/
int main(void)
{
uchar8_t key_val = 0xFF;
while (1) {
key_val = key_scan();
if (key_val != 0xFF) {
digit_ctrl(key_val);
} else {
digit_ctrl(DS_code[16]);
}
}
}
uchar8_t key_scan(void)
{
uchar8_t X_val = 0;
uchar8_t Y_val = 0;
uchar8_t K_val = 0xFF;
/* Step 1> Find X pointer */
KEY_PORT = 0x0F; // Write 0000 1111;
if (KEY_PORT != 0x0F) {
switch (KEY_PORT) {
case 0x0E:
X_val = 0;
break;
case 0x0D:
X_val = 4;
break;
case 0x0B:
X_val = 8;
break;
case 0x07:
X_val = 12;
break;
default:
X_val = 0;
break;
}
/* Step 2> Find Y pointer */
KEY_PORT = 0xF0; // Write 1111 0000;
if (KEY_PORT != 0xF0) {
switch (KEY_PORT) {
case 0xE0:
Y_val = 0;
break;
case 0xD0:
Y_val = 1;
break;
case 0xB0:
Y_val = 2;
break;
case 0x70:
Y_val = 3;
break; // Lost the 'break'
default:
Y_val = 0;
break;
}
/* Step 3> Find Key code */
K_val = X_val + Y_val;
}
} else {
K_val = 0xFF;
}
return K_val;
}
/**
* Ctrl digit number
*/
void digit_ctrl(uchar8_t num)
{
NUM_PORT = DS_code[num];
}
// end file