目录
书上例程:实验板上电时,数码管不显示,顺序按下矩阵键盘后没再数码管上依此显示0~F,6个数码管同时静态显示即可
一个用JX-TX-1C实验板制作的24小时以内的时间显示或者倒数计数模式的闹钟(相较以前有所更新)示例
4.2 矩阵键盘检测
独立键盘与单片机相连时每一个案件都需要单片机的一个I/O口,若单片机系统需要较多按键则独立按键会占用过多的I/O口资源。为节省I/O口,因纳入矩阵键盘。以4×4矩阵键盘为例讨论起工作原理和检测方法——16个按键排成4行4列,4行4列一共8根线,连接到单片机的8个I/O口上。
TX-1C上的连接图原理如下:
矩阵键盘检测是否按下原理同独立键盘——检测该键对应的I/O口是否为低电平,矩阵键盘两端都与I/O口相连,因此检测时需认为通过单片机I/O口送出低电平。检测时,送一列为低电平,其余几列为高电平(确定了列),再检测哪一行为低电平即可确定按下键的行列号,如此轮流检测各列各行,即可检测完所有的按键,反之先检测行线同理可行。
其中,TX-1C上的4行S6~S21的8条线分别与单片机的P3口相连——4行分别连P3.0~P3.3,4列分别于单片机的P3.4~P3.7(注意这里与独立按键占用的I/O口重复了,为防止发生51单片机独立键盘和矩阵键盘引脚定义相同IO口导致的问题(串口干扰):在扫描独立按键程序的开头加一句,P3=0xff;)。
当无按键闭合时,P3.0~P3.3与P3.4~P3.7之间开路。当有键闭合时,与闭合键相连的两条I/O口线之间短路。判断有无按键按下的方法是:
(1)置列线P3.4~P3.7为输入状态,从行线P3.0~P3.3输出低电平,读入列线数据,若某一列线为低电平,则该列线上有键闭合。
(2)行线轮流输出低电平,从列线P3.4~P3.7读入数据,若有某一列为低电平,则对应行线上有键按下。综合一二两步的结果,可确定按键编号。但是键闭合一次只能进行一次键功能操作,因此须等到按键释放后,再进行键功能操作,否则按一次键,有可能会连续多次进行同样的键操作。
检测矩阵键盘语句说明:(以扫描第一行按键为例)
注:关于位运算可以参考文章:http://t.csdnimg.cn/dAUY9
为方便编程和查找,在下面的例程中进行了如下的优化:
(1)将矩阵键盘行线存入code数组中便于表示和查找
uchar code matrixkeyboard_row_table[]={ //矩阵键盘行线
0xfe, //第一行线
0xfd, //第二行线
0xfb, //第三行线
0xf7 //第四行线
};
(2)将矩阵键盘键位编码存入code数组中便于表示和查找
uchar code matrixkeyboard_table[]={ //矩阵键盘按钮编号
0xee,0xde,0xbe,0x7e, //第一行key1~4
0xed,0xdd,0xbd,0x7d, //第二行key5~8
0xeb,0xdb,0xbb,0x7b, //第三行key9~12
0xe7,0xd7,0xb7,0x77 //第四行key13~16
};
(3) 由于(1)无法采用switch case语句(由于case后必须跟的是常数),因此判断temp具体值部分修改为(具体的情况请代入下面的例程):
temp=P3;
if(temp == matrixkeyboard_table[4*i-4]) key_num=4*i-3;
if(temp == matrixkeyboard_table[4*i-3]) key_num=4*i-2;
if(temp == matrixkeyboard_table[4*i-2]) key_num=4*i-1;
if(temp == matrixkeyboard_table[4*i-1]) key_num=4*i;
书上例程:实验板上电时,数码管不显示,顺序按下矩阵键盘后没再数码管上依此显示0~F,6个数码管同时静态显示即可
(和原书所附程序有所不同,原理一致,相比之下更便捷更简短)
#include<reg52.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6; //声明U1锁存器的锁存端
sbit wela=P2^7; //声明U2锁存器的锁存端
uchar code dula_table[]={ //段选数码库
0x3f,0x06,0x5b,0x4f, // 0,1,2,3
0x66,0x6d,0x7d,0x07, //4,5,6,7
0x7f,0x6f,0x77,0x7c, //8,9,10,11
0x39,0x5e,0x79,0x71 //12,13,14,15
};
uchar code matrixkeyboard_row_table[]={ //矩阵键盘行线
0xfe, //第一行线
0xfd, //第二行线
0xfb, //第三行线
0xf7 //第四行线
};
uchar code matrixkeyboard_table[]={ //矩阵键盘按钮编号
0xee,0xde,0xbe,0x7e, //第一行key1~4
0xed,0xdd,0xbd,0x7d, //第二行key5~8
0xeb,0xdb,0xbb,0x7b, //第三行key9~12
0xe7,0xd7,0xb7,0x77 //第四行key13~16
};
void main()
{
void delayxms(uint xms); //延时函数 ms为单位
void matrixkeyscan(); //矩阵键盘输入函数
void display(uchar key_num); //数码管显示函数
dula=1;
P0=0; //关闭所有数码管段选
dula=0;
wela=1;
P0=0xc0; //打开所有数码管的位选
wela=0;
while(1)
{