4×4 矩阵式键盘电路的改进

本文向大家推荐一个精简IO接口的4×4键盘电路,该键盘电路仅仅使用4条IO接口引线,即可完成一般需要8位接口才能完成的功能。

在51单片机系统中,经常使用4×4键盘,一般情况下,都是使用一个8位的接口,外接16个按键。
下图就是一个常规的4×4键盘电路图。

4×4 矩阵式键盘电路的改进 - 非著名博主 - 电子信息角落

这种常规的矩阵键盘电路,相信大家都司空见惯了,好多人都会编写它的驱动程序。
图中使用了P0口的8个引脚(P0.0~P0.7),分别驱动键盘的行和列。按键的编号,在图中分别标注了0~F。

检测按键的一般的思路是在四个列线,分别输出一个低电平,然后输入行线,逐行检测是否存在低电平。
如果在某行有低电平出现,就说明该行、列的交叉点上的按键,被按下了。

其实,这些行、列引线,是“分时”工作的,当在某一列输出低电平的时候,其它的列,输出的就是高电平。
如果利用这些输出高电平的列,进行输入,那么就可以极大的节省IO接口的引线数量。
基于这个道理,在上图中,下面的四个列驱动引线(P0.4~P0.7),就完全可以省去,只是使用行驱动的引脚(P0.0~P0.3)来分时输出低电平即可。
电路见下图。

4×4 矩阵式键盘电路的改进 - 非著名博主 - 电子信息角落

为了对引脚之间进行隔离,图中加上了四个二极管,确保只有在引脚输出低电平的时候,方可把键盘中相应的列置为0。

针对这个电路,对按键的检测方法,和常规的4×4键盘检测思路是相同的,例如:
当在P0.0输出低电平,即最左边的列为0,这时检测P0.1、P0.2及P0.3是否为0,可以判断最左边的三个按键是否按下;
当在P0.1输出低电平,即左边第二列为0,这时检测P0.0、P0.2及P0.3是否为0,可以判断左边第二列的三个按键是否按下;
…………;
这个检测按键是否按下的思路非常简单,会编写常规4×4键盘驱动程序的网友,肯定都会编写出来这种电路的驱动程序。

因为行和列使用了相同的IO引线,实际上,连接在同一个引线的行、列交叉点处的按键,就已经失效了,那么就把把原来的按键,移动出来,把二极管画在交叉点,电路如下所示。

4×4 矩阵式键盘电路的改进 - 非著名博主 - 电子信息角落


再把移出来四个按键连接在IO引线,另一端直接接地;把其它按键的编号,再整理一下,就成了下图电路。

4×4 矩阵式键盘电路的改进 - 非著名博主 - 电子信息角落


这个电路比常规的4×4键盘电路仅仅多用了四个二极管,但是却节省了四条IO接口引线,这个意义是十分巨大的。
按照这个电路的设计思路,使用 n 条IO接口引线,就可以驱动 n×n 个按键。
那么用5个IO引脚,就可以驱动5×5的键盘,这就足以满足各种应用了。
网上也有一些其它类型的节省接口的键盘电路,但是都有不足,不是电路过于复杂,就是驱动的按键个数较少,远远不及本电路简单实用。

做而论道已经按照这个电路制作了PCB板,外形和常规4×4键盘电路板相差无几。二极管体积很小,布线并没有障碍。

实践证明,这是个完美的精简接口的4×4键盘电路,不仅可以用在51单片机系统,在使用其它MCU组建的电路中同样适用。

针对这个电路,做而论道已经用汇编语言和C语言编写出了驱动程序,因为汇编语言可以使用“位操作”指令,所以程序的比较简单;C语言的程序,就显得累赘一些。
程序暂时就不公布了,有兴趣的网友可以来讨论。

好的,下面是使用Keil5编写4*4矩形键盘模块三位数以内加减乘除计算器的代码: ```c #include <reg52.h> #define uchar unsigned char #define uint unsigned int uchar code keymap[4][4] = { // 键盘按键映射表 {'1', '2', '3', '+'}, {'4', '5', '6', '-'}, {'7', '8', '9', '*'}, {'C', '0', '=', '/'} }; uchar tmp, num1, num2, op, result; // 定义变量 sbit D0 = P2^0; // 显示数码管位选引脚 sbit D1 = P2^1; sbit D2 = P2^2; sbit D3 = P2^3; sbit LSA = P2^4; // 显示数码管片选引脚 sbit LSB = P2^5; sbit LSC = P2^6; void delay(uint t) // 延时函数 { uint i, j; for(i=0; i<t; i++) { for(j=0; j<120; j++); } } void scan_key() // 扫描键盘函数 { uchar i, j; for(i=0; i<4; i++) { P1 = 0x0f ^ (0x01 << i); // 设置行引脚电平 tmp = P1; // 读取列引脚电平 for(j=0; j<4; j++) { if(!(tmp & (0x01 << j))) // 判断是否有按键按下 { delay(10); // 延时去抖动处理 if(!(tmp & (0x01 << j))) // 再次判断是否有按键按下 { while(!(tmp & (0x01 << j))); // 等待按键释放 if(keymap[i][j] >= '0' && keymap[i][j] <= '9') // 如果是数字键 { if(op == 0) // 如果还没有操作符 { num1 = num1 * 10 + (keymap[i][j] - '0'); // 计算第一个数 P0 = num1; // 显示第一个数 } else // 如果已经有操作符 { num2 = num2 * 10 + (keymap[i][j] - '0'); // 计算第二个数 P0 = num2; // 显示第二个数 } } else if(keymap[i][j] == 'C') // 如果是清除键 { num1 = 0; num2 = 0; op = 0; P0 = 0; // 清除显示 } else if(keymap[i][j] == '=') // 如果是等于键 { switch(op) { case '+': result = num1 + num2; break; case '-': result = num1 - num2; break; case '*': result = num1 * num2; break; case '/': result = num1 / num2; break; default: break; } num1 = result; num2 = 0; op = 0; P0 = result; // 显示结果 } else // 如果是操作符键 { op = keymap[i][j]; } } } } } } void display(uchar num) // 显示数码管函数 { switch(num) { case 0: LSA = 0, LSB = 0, LSC = 0, D0 = 1, D1 = 1, D2 = 1, D3 = 1; break; case 1: LSA = 1, LSB = 0, LSC = 0, D0 = 0, D1 = 1, D2 = 1, D3 = 1; break; case 2: LSA = 0, LSB = 1, LSC = 0, D0 = 1, D1 = 0, D2 = 1, D3 = 1; break; case 3: LSA = 1, LSB = 1, LSC = 0, D0 = 0, D1 = 0, D2 = 1, D3 = 1; break; case 4: LSA = 0, LSB = 0, LSC = 1, D0 = 1, D1 = 1, D2 = 0, D3 = 1; break; case 5: LSA = 1, LSB = 0, LSC = 1, D0 = 0, D1 = 1, D2 = 0, D3 = 1; break; case 6: LSA = 0, LSB = 1, LSC = 1, D0 = 1, D1 = 0, D2 = 0, D3 = 1; break; case 7: LSA = 1, LSB = 1, LSC = 1, D0 = 0, D1 = 0, D2 = 0, D3 = 1; break; case 8: LSA = 0, LSB = 0, LSC = 0, D0 = 1, D1 = 1, D2 = 1, D3 = 0; break; case 9: LSA = 1, LSB = 0, LSC = 0, D0 = 0, D1 = 1, D2 = 1, D3 = 0; break; default: break; } } void main() { while(1) { scan_key(); // 扫描键盘 display(num1 % 10); // 显示个位数字 delay(5); display(num1 / 10 % 10); // 显示十位数字 delay(5); display(num1 / 100); // 显示百位数字 delay(5); } } ``` 在以上代码中,我们通过扫描键盘来获取用户的输入,并根据不同的按键进行相应的计算操作。同时,我们还使用了数码管来显示计算结果。需要注意的是,由于使用了延时函数来控制数码管的显示,可能会导致按键响应速度变慢,因此可以考虑使用定时器来代替延时函数来控制数码管的显示。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值