实验原理:
检测按键的方法:
键盘电路图:
(一)行列扫描法(代码较复杂)
先输入一列为0,其余为1(列坐标的确定),轮流检测各行是否有输出0(行坐标的确定)
接着依次输入下一列为0,其余列为1,所有列完成即可检测完所有按键。
(二)线翻转法
置列线(输出线)全部为0,此时行线(输入线)若有输出为0则该行有按键被按下。
置行线(输出线)全部为0,此时列线(输入线)若有输出为0则该列有按键被按下。
实验代码:
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
void delay_10us(u16 ten_us); //延时函数
u8 key_matrix_ranks_scan(void);
u8 key_matrix_filp_scan(void);
#define KEY_MATRIX_PORT P1
#define SMG_PORT P0
u8 gsmg_code[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
void main() //按键按下S1-S16 对应LED等点亮0-F
{
u8 key=0;
while(1)
{
key=key_matrix_filp_scan();
if(key!=0)
SMG_PORT=~gsmg_code[key-1]; //上面数组为共阴编码,取反得到共阳编码
}
}
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
u8 key_matrix_filp_scan(void) //线翻转法扫描
{
u8 key_value=0;
KEY_MATRIX_PORT=0x0f; //列扫描
if(KEY_MATRIX_PORT!=0x0f)
{
delay_10us(1000); //消抖
if(KEY_MATRIX_PORT!=0x0f)
{
switch(KEY_MATRIX_PORT)
{
case 0x07:key_value=1;break;
case 0x0b:key_value=2;break;
case 0x0d:key_value=3;break;
case 0x0e:key_value=4;break;
}
KEY_MATRIX_PORT=0xf0; //行扫描
switch(KEY_MATRIX_PORT)
{
case 0x70:key_value=key_value;break;
case 0xb0:key_value=key_value+4;break;
case 0xd0:key_value=key_value+8;break;
case 0xe0:key_value=key_value+12;break;
}
while(KEY_MATRIX_PORT!=0xf0);
}
}else
key_value=0; //没有按键按下 返回0
return key_value; //返回按键编号
}
u8 key_matrix_ranks_scan(void) //行列式扫描
{
u8 key_value=0;
KEY_MATRIX_PORT=0xf7; //第一列低电平
if(KEY_MATRIX_PORT!=0xf7)
{
delay_10us(1000);
switch(KEY_MATRIX_PORT)
{
case 0x77:key_value=1;break;
case 0xb7:key_value=5;break;
case 0xd7:key_value=9;break;
case 0xe7:key_value=13;break;
}
}
while(KEY_MATRIX_PORT!=0xf7); //等待按键松开
KEY_MATRIX_PORT=0xfb;
if(KEY_MATRIX_PORT!=0xfb)
{
delay_10us(1000);
switch(KEY_MATRIX_PORT)
{
case 0x7b:key_value=2;break;
case 0xbb:key_value=6;break;
case 0xdb:key_value=10;break;
case 0xeb:key_value=14;break;
}
}
while(KEY_MATRIX_PORT!=0xfb);
KEY_MATRIX_PORT=0xfd;
if(KEY_MATRIX_PORT!=0xfd)
{
delay_10us(1000);
switch(KEY_MATRIX_PORT)
{
case 0x7d:key_value=3;break;
case 0xbd:key_value=7;break;
case 0xdd:key_value=11;break;
case 0xed:key_value=15;break;
}
}
while(KEY_MATRIX_PORT!=0xfd);
KEY_MATRIX_PORT=0xfe;
if(KEY_MATRIX_PORT!=0xfe)
{
delay_10us(1000);
switch(KEY_MATRIX_PORT)
{
case 0x7e:key_value=4;break;
case 0xbe:key_value=8;break;
case 0xde:key_value=12;break;
case 0xee:key_value=16;break;
}
}
while(KEY_MATRIX_PORT!=0xfe);
return key_value;
}
实验结果:
与预期一致,当键盘按下S1-S16对应数码管点亮0-F字符。



