在AT89S52_单片机上连接矩阵键盘-51单片机与4x4键盘
1
在在在在 AT89S52单片机上连接矩阵键盘单片机上连接矩阵键盘单片机上连接矩阵键盘单片机上连接矩阵键盘
本文说说矩阵键盘和 51单片机连接的情况。先说下独立键盘的应用。
当一个单片机系统只需要少量的键盘的时候 用简单的独立键盘最好 见下图
比如说按一个键亮一个灯就可以这样搞 如果说真的要求就这么简单 其实连单片机也可以
省了 我自己感觉哈 学会用单片机的时候 就开始不喜欢用以前的电路啦 老是有一种单片
机可以搞定所有问题的感觉 其实这样不好 但是单片机确实很“万能”
但是当系统需要比较多的键盘...
1
在在在在 AT89S52单片机上连接矩阵键盘单片机上连接矩阵键盘单片机上连接矩阵键盘单片机上连接矩阵键盘
本文说说矩阵键盘和 51单片机连接的情况。先说下独立键盘的应用。
当一个单片机系统只需要少量的键盘的时候 用简单的独立键盘最好 见下图
比如说按一个键亮一个灯就可以这样搞 如果说真的要求就这么简单 其实连单片机也可以
省了 我自己感觉哈 学会用单片机的时候 就开始不喜欢用以前的电路啦 老是有一种单片
机可以搞定所有问
的感觉 其实这样不好 但是单片机确实很“万能”
但是当系统需要比较多的键盘时 采用矩阵键盘就比较方便 见下图
常见的遥控器 大楼安保密码键盘 保险柜的键盘 电话机的键盘 手机键盘 上网聊 QQ 的键
盘 等等等等 都是这样的
4x4矩阵键盘检测按键的方法是
先拉低第一行的电平,检测 1~4列有无键按下 如有返回键值 如无看下行
再拉低第二行的电平,检测 1~4列有无键按下 如有返回键值 如无看下行
先拉低第三行的电平,检测 1~4列有无键按下 如有返回键值 如无看下行
再拉低第四行的电平,检测 1~4列有无键按下 如有返回键值 如无则返回无键按下
2
下面出个检测矩阵键盘的函数秀秀哈(主函数略过)
采用最原始的想法哈 (除特殊说明外本资料里面程序均调试正常工作)
unsigned char Key_Scan(void)//键盘扫描函数 如果有键按下返回键 ASC值 若无返回 0
{
P1=0XF0;
if(P1!=0XF0)//先确定是否有键按下
{
//--------------1------------------------------------
P1=0XFE;//第一次把 P1^7拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xee: return '0';//P1^3 低 返回‘0’
case 0xde: return '1';//P1^2 低 返回‘1’
case 0xbe: return '2';//P1^1 低 返回‘2’
case 0x7e: return '3';//P1^0 低 返回‘3’
default: break;//没有本行的键按下 继续下面扫描
}
//----------------------------------------------------
//-------------2--------------------------------------
P1=0XFD;//第二次把 P1^6拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xed: return '4';//P1^3 低 返回‘4’
case 0xdd: return '5';//P1^2 低 返回‘5’
case 0xbd: return '6';//P1^1 低 返回‘6’
case 0x7d: return '7';//P1^0 低 返回‘7’
default: break;//没有本行的键按下 继续下面扫描
}
//----------------------------------------------------
//-------------3--------------------------------------
P1=0XFB;//第三次把 P1^5拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xeb: return '8';//P1^3 低 返回‘8’
case 0xdb: return '9';//P1^2 低 返回‘9’
case 0xbb: return 'A';//P1^1 低 返回‘A’
case 0x7b: return 'B';//P1^0 低 返回‘B’
default: break;//没有本行的键按下 继续下面扫描
}
3
//----------------------------------------------------
//-------------4--------------------------------------
P1=0XF7;//第三次把 P1^4拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xe7: return 'C';//P1^3 低 返回‘C’
case 0xd7: return 'D';//P1^2 低 返回‘D’
case 0xb7: return 'E';//P1^1 低 返回‘E’
case 0x77: return 'F';//P1^0 低 返回‘F’
default: break;//没有键按下 继续下面
}
}
return 0;
}
希望新入行的兄弟上机试一下这段函数 可以配个 LCD来做显示 也可以用串口发回电脑显
示 否则光是看看印象不会很深的 严重不建议简单电路使用软件仿真 还是要 搭板子 编程
烤片 试验的
上面函数是直接把 矩阵键盘检测按键的方法 翻译成C程序的 这样直接做当然是有很多问
题的 但是在拿到一个问题后不知道如何程序化不知道如何程序化不知道如何程序化不知道如何程序化的前提下 不妨就这样先直译 译完了 再确
定 功能是否实现 功能是否有缺陷 如何改良 。
上面的函数 功能是实现了 但是有 2个致命的缺陷 (试过程序就知道)
1 没有键盘消抖和松手检测
2 代码过长
关于没有键盘消抖和松手检测的现象我不想多说了 请试下就知道效果了
说说如何在上步程序的基础上加上
请看改良过 1次的函数
void Delay(unsigned int Time)//新添加的延时函数
{
unsigned char t;
while(Time--)
{
for(t=0;t<100;t++);
}
}
4
unsigned char Key_Scan(void)//键盘扫描函数 如果有键按下返回键 ASC值 若无返回 0
{
P1=0XF0;
if(P1!=0XF0)//先确定是否有键按下
{
Delay(5);//稍微延时 避开按键前期抖动
if(P1!=0xf0)//再次检测是否按下
{
//--------------1------------------------------------
P1=0XFE;//第一次把 P1^7拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xee: while(P1!=0xfe);return '0';//P1^3 低 while();是在等待松手
松手后返回‘0’下面相同
case 0xde: while(P1!=0xfe);return '1';//P1^2 低 返回‘1’
case 0xbe: while(P1!=0xfe);return '2';//P1^1 低 返回‘2’
case 0x7e: while(P1!=0xfe);return '3';//P1^0 低 返回‘3’
default: break;//没有本行的键按下 继续下面扫描
}
//----------------------------------------------------
//-------------2--------------------------------------
P1=0XFD;//第二次把 P1^6拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xed: while(P1!=0xfd);return '4';//P1^3 低 返回‘4’
case 0xdd: while(P1!=0xfd);return '5';//P1^2 低 返回‘5’
case 0xbd: while(P1!=0xfd);return '6';//P1^1 低 返回‘6’
case 0x7d: while(P1!=0xfd);return '7';//P1^0 低 返回‘7’
default: break;//没有本行的键按下 继续下面扫描
}
//----------------------------------------------------
//-------------3--------------------------------------
P1=0XFB;//第三次把 P1^5拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xeb: while(P1!=0xfb);return '8';//P1^3 低 返回‘8’
case 0xdb: while(P1!=0xfb);return '9';//P1^2 低 返回‘9’
case 0xbb: while(P1!=0xfb);return 'A';//P1^1 低 返回‘A’
case 0x7b: while(P1!=0xfb);return 'B';//P1^0 低 返回‘B’
default: break;//没有本行的键按下 继续下面扫描
}
//----------------------------------------------------
5
//-------------4--------------------------------------
P1=0XF7;//第三次把 P1^4拉低
switch (P1)//测 P1^0~~~P1^3有没有低的
{
case 0xe7: while(P1!=0xf7);return 'C';//P1^3 低 返回‘C’
case 0xd7: while(P1!=0xf7);return 'D';//P1^2 低 返回‘D’
case 0xb7: while(P1!=0xf7);return 'E';//P1^1 低 返回‘E’
case 0x77: while(P1!=0xf7);return 'F';//P1^0 低 返回‘F’
default: break;//没有键按下 继续下面
}
}
return 0;
}
}
这次试机的时候发现按一个键出 1个字了吧(当然键盘不能超抖)
嘿嘿 程序就是这样调试的 先把功能搞出来 然后根据毛病再改良 老手也是这样来的 新人
更是如此 慢慢来 不要再不熟悉的情况下追求完美 会晕的 另外提下 程序这种东西永远没
有最完美 只有更完美 当你深深的感觉到 你编的程序在某种情况下是为了弥补硬件上的缺
陷的时候 那恭喜你 你就大概齐明白了为啥要用程序驱动电路了 呵呵
这样做了以后 上面红字第 1 个的毛病就克服了 但是更突出的是第 2 行红字的毛病了
咱们再改
细看程序 能发现程序中有很多一样或者相似的内容 具体的暂时先表管 只要是有这个感觉
就好办 以后别的函数也一样哈 先要有这个感觉 然后再细细琢磨你的感觉 我告诉大家只
要是有重复的东西就可以用循环搞定的 这也是简化代码的最直接办法
另外再扯点别的阿 计算机是计算的 有些时候 越是那种类似于 1+2+3+1000 之类的问题越
是要交给计算机算 不要人算 要知道 它算得比人快 N倍
就说加法这个问题 如果按照人正常的想法 程序是这样编的
void ADD1_1000(void)//(此段函数未调试 只是说明问题)
{
unsigned int sum;
sum=1+2+3+4+5+......1000;
}
这样写是会死人的 要么累死 要么被老大秒杀 看看下面的
void ADD1_1000(void) //(此段函数未调试 只是说明问题)
{
unsigned int sum,i;
while(i!=1001)
{
sum=sum+i;
i++;
}
6
}
比较老实的弄法 有学生的风格 下面看个玩得更拽的
void ADD1_1000(void) //(此段函数未调试 只是说明问题)
{
unsigned int sum,i;
while(i!=1001)
{
sum+=(i++);
}
}
其实和第 2 个是一个东西 只是压缩了一行 其实不建议这样压缩的 这样做完了 只能是程
序的可读性下降了(对于新人) 其他的好处不是很大 咱们以后也是阿 有时候是需要玩下
拽的(即特殊的时候) 但平时工作能老老实实就老老实的比较好 毕竟写完的程序还是自己
粘的时候比较多
再说了 以后编程很可能是论行算钱的 就更没有必要压缩这些不需要压缩的行了 但是如果
咱们的 Key_Scan()函数不压缩的话基本类似第一个加法函数也会被老大秒杀的 这都扯到
哪里了 言归正传哈
咱们再说说这个键盘哈 万变不离上面的紫色的内容 因为那是基本思想 但是发现再咱们检
测按键的时候只是检测了 P10~P13 的内容 其他的咱们不用管的 高位咱们依次送出的是
e,d,b,7 (在扯的里面再嵌套一些扯的 有些个数字是需要咱们敏感的 咱先不说是把 2 进制
数背的滚瓜烂熟 咱又不是计算机 但是看到0xfe的时候要立马有一个只亮一盏灯的概念 不
是说算了 10 分钟才能闹明白的 就说键盘这里 常用的就是 0xf0 和 0x0f 一看就得知道是前
一半和后一半的关系 还有诸如 看到 e,d,b,7 就要有一种 3个 1和 1个 0的掺和的想法 )知
道了这个咱们就可以压缩代码 看看下面的函数 少了很多 用 1 个 for 循环解决的问题。值
得说的就是很好的用了变量 i的次数和 case后面的常量 确定一个键值
unsigned char Key_Scan(void)//键盘扫描函数 如果有键按下返回键 1-15 若无返回 'E'
{
unsigned char i, key;
unsigned char k=88;
P1=0xf0;
if(P1!=0xf0)// 这就算是进来了
{
P1=0xfe;
for(i=0;i<4;i++)//四次扫描
{
key=P1&0xf0;//屏蔽掉低 4位 只保留检测回来的位
switch(key)
{
case 0xe0: k=i;break;//能记录 0-3
case 0xd0: k=i+4;break;//能记录 4-7
7
case 0xb0: k=i+8;break;//能记录 8-11
case 0x70: k=i+12;break;//能记录 12-15
default: ;
}
P1=(P1<<1)+1;//把 P1口的 0的位向左移动
if(k!=88)break;//检测到按键后退出 for循环
}
P1=0xf0;
while(P1!=0xf0);//松手检测
return(k);//返回键值 返回的数字不是 ASC值
}
else return 'E';//没有键按下 返回'E'
}
看看咱们这个程序是如何压缩代码的 对比着上面的看 是不是很袖珍了 代码压缩也是一门
艺术 不能随便乱压 这个键盘扫描的函数可以存在电脑里面了 以后再需要键盘扫描的时候
直接贴上改改就可以了 所以编程就是很多大虾说的 Ctrl+C 和 Ctrl+V 嘿嘿
好了键盘的事情先就罗嗦到这里了 强烈建议新人一定要做硬件试验来巩固知识 切忌看看
程序就了事
好了 留 4个作业题
1 如何能判断每个键按下的时间??因为这个特别是在键盘特别少的情况下 一个键按下时
间的长短 代表的意思是不同的。(要编程的思想或者程序)
2 如果单片机只有 P10,P11俩个端口的时候 你能想到最多能连接多少键盘??
(要电原理图和编程思想或者程序)
3如何在键盘被按下时才通知主函数或者处理键盘输入的数据 而平时不需要一直扫描键盘
(要电原理图和编程思想或者程序)
4如何在键盘少的情况下(比如 3个按键)开发按键的第 2功能(比如某表中有三个键 SET
UP DOWN SET键按 1次秒闪 2次分闪 3次时闪 UP DOWN是谁闪调谁)
(编程思想或者程序)
以上 4道作业题欢迎大家交作业哈 2周后 咱们开新贴讨论这 4道题
。
有问题 意见 建议 等等请发邮件 unifax@163.com
Unifax 2009.4.9
本文档为【在AT89S52_单片机上连接矩阵键盘-51单片机与4x4键盘】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。