
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人
3.16 4×4键盘矩阵控制条形LED显示
当按键较多时会占用更多的控制器端口,为减少对端口的占用,本例使用4×4 键盘矩阵,这样大大减少了端口占用,但识别按键的代码比独立按键的代码要复杂一些。本例运行过程时所点亮的LED个数与按键键值相等,例如,按下K1时,第1只LED点亮,按下K2时前2只LED点亮,按下K10时第1~10只LED点亮。
本例电路及运行效果如图3-13所示。

图3-13 4×4键盘矩阵控制条形LED显示电路
程序设计调试与实训:
本例键盘矩阵行线连接P0.0~P0.3,列线连接P0.4~P0.7,扫描过程如下:
程序首先判断是否有键按下。为判断16个按键中是否有键按下,程序首先在4条行线上放置4个0,即在P1端口输出0xF0,如果有任一按键按下,则4条列线上必有一位为0。
如果已有键按下,则判断按键所在行、列位置,并返回按键序号。代码中行扫描码sCode初值为0xFE(11111110),通过将该值循环右移,可对P1.0~P1.3对应的4行逐行发送0,每次发送扫描码后即判断高4位的4个1中是否有0出现,如果出现0则说明按键在该行上,这时可将发送的低4位与读取的高4位取反,也就是P1取反,这样P1中将出现2个1,其余位均变为0,2个1分别处在低4位和高4位中,高低4位中1所处的位置各有4种可能,共有16种可能,对应16个不同按键,根据取反后的值查询键盘矩阵按键特征码表,即可得到按键序号。
另外,读者要注意在代码中用延时对按键进行消抖。
读者可将电路中的按键由纵向编号改为横向编号,重新修改代码,看能否得到正确的运行结果。
源程序代码:
//----------------------------------------------------------------- // 名称: 4×4 键盘矩阵控制条形LED显示 //----------------------------------------------------------------- // 说明: 运行本例时,按下的按键键值越大,点亮的LED越多,例如,按下K1时 // 点亮第1只LED,按下K2时点亮第1,2只LED,按下K16时全部LED点亮。 //----------------------------------------------------------------- #include <reg51.h> #include <intrins.h> #define uchar unsigned char #define uint unsigned int //0~9,A~F的数码管段码,最后一个是黑屏 uchar code DSY_CODE[]= { 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x00 }; //键盘矩阵按键特征码表 uchar code KeyCodeTable[] = { 0x11,0x12,0x14,0x18,0x21,0x22,0x24,0x28,0x41,0x42,0x44,0x48,0x81,0x82, 0x84,0x88}; //----------------------------------------------------------------- // 延时 //----------------------------------------------------------------- void Delay() { uchar i; for(i = 0; i < 200; i++); } //----------------------------------------------------------------- // 键盘矩阵扫描 //----------------------------------------------------------------- uchar Keys_Scan() { uchar sCode,kCode,i,k; //低4位置0,放入四行 P1 = 0xF0; //如果高4位出现0则有键按下 if ((P1 & 0xF0) != 0xF0) { Delay(); if ((P1 & 0xF0) != 0xF0) { //行扫描码初值 sCode = 0xFE; //对4行分别进行扫描 for (k = 0; k < 4; k++) { P1 = sCode; if (( P1 & 0xF0) != 0xF0) { kCode = ~P1; //查表得到按键序号并返回 for( i = 0; i< 16; i++) if (kCode == KeyCodeTable[i]) return i; } else sCode = _crol_(sCode,1); } } } return -1; } //----------------------------------------------------------------- // 主程序 //----------------------------------------------------------------- void main() { //按键序号,-1表示无按键 uchar KeyNo = -1; uchar i,P2_LED,P3_LED; while(1) { //扫描键盘获取按键序号KeyNo KeyNo = Keys_Scan(); if (KeyNo != -1) { P2_LED = 0xFF; P3_LED = 0xFF; //键值越大,点亮的LED越多 for (i = 0; i <= KeyNo; i++) { if ( i < 8) P3_LED >>= 1; else P2_LED >>= 1; } //点亮条形LED P3 = P3_LED; P2 = P2_LED; } } }