8051矩阵键盘

jidumo 2017-07-25 10:20:32
题目要求是:按下第一个键,让数码管显示1,第二按键按下,显示2,以此类推。
1、只列举了4*4矩阵键盘第一行的情况在temp=P3这个语句中不太理解,不懂为什么按下第一行的第一个按键可以在数码管显示相应的数字,按第二个也可以显示相应的数字,第三,第四也可以。
2、不太懂I\O口置1的输入模式,是不是只要从I\O口接收数据,便先置1,接着直接读取I\O口的数据即可吗?那么每一次读取前都要置1 吗?
问题描述有所欠缺,若有不够好的地方,希望提出来,我会完善信息。愿有人能帮忙解决问题,感激不尽。


#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit dula=P2^6; //数码管段选,锁存器控制
sbit wela=P2^7; //数码管位选,锁存器控制
uchar num,temp;
uchar code table[]={ //数码管编码
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71};
void delay(uint z);

void main()
{
dula=1;
P0=0; //给段选送数据
dula=0;
wela=1;
P0=0xc0; //给位选送数据,选中所有数码管
wela=0;
while(1)
{
P3=0xfe; //P3口接矩阵键盘
temp=P3;
temp=temp&0xf0;
while(temp!=0xf0) //若temp=0xf0,则第一行没有按键被按下。若不等于,则有按键被按下
{
delay(5); //延时消抖
temp=P3; //消抖后再读取P3口的数据
temp=temp&0xf0; //此时读取的数据便是稳定的
while(temp!=0xf0)
{
temp=P3; //不懂
switch(temp)
{
case 0xee: num=1;
break;
case 0xde: num=2;
break;
case 0xbe: num=3;
break;
case 0x7e: num=4;
break;
}

dula=1; //打开段选
P0=table[num-1]; //给数码管输送数据
dula=0; //保持
}
}
}
}

void delay(uint z)
{
uchar x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
...全文
297 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
侦探蜡笔小新 2017-08-03
  • 打赏
  • 举报
回复
引用 11 楼 jidumo 的回复:
[quote=引用 8 楼 g62r83t27 的回复:] [quote=引用 6 楼 jidumo 的回复:] [quote=引用 4 楼 g62r83t27 的回复:] 首先我来理解你的4*4的矩阵键盘 1,按键按下对应IO口电平是低电平,按键弹起对应IO口电平为高 2,每个按键反馈给两个IO口,分别表示该按键所在的行与列 3,P3高4位对应4*4矩阵的4列,P3低四位对应4*4矩阵的4行,如下图,第一行第一列按键按下时,P3.1和P3.5对应低电平 while(temp!=0xf0)其实可以写成while(temp )这样好理解 然后来说说IO口输入输出模式,正好回答你的第二个问题。 1, 51单片机IO口为双向输入输出模式,意思是如下1.1和1.2: 1.1,给P3口赋值,表示P3口要输出高电平或低电平 如P3 = 0xFE;表示将P3.0拉低, P3.2-P3.7拉高 1.2,读P3口值,表示要读取P3口当前的状态,如temp = P3,意思是读取当前P3口状态。 这种状态是实时的,如第一行第一列按键按下,则temp的值应为11101110b,即0xEE,具体如下: 第一行第一列 对应的P3.0和P3.4的状态立即被拉低(按键将IO口与地短接),位值为0。 反之按键弹起则对应IO口状态立即被拉高(上拉电阻的功劳),位值为1。
当检测到有按键按下,程序运行到temp=P3,接着执行switch语句。退出switch语句后,回到第二个while(temp!=0xf0),在这个时候,程序怎么检测到下一次按键[/quote] 你的while(1)会不停地给P3赋值,P3 = 0小FE, 属于强制拉高,此时如果按键未弹起,强制拉高是无效的, 你的程序靠内两层循环来消除抖动实际上是多余的,调整delay(5); //延时消抖 这个值即可,更好的办法是消抖前后检测是否是同一个按键,不是的话不处理[/quote] 首先,非常感谢你的回答。我看懂了你的回复。但是我还有疑问,就是检测按键按下后,程序怎么退出while循环。第二个疑问:向IO口写1才能配置为输入模式,那是不是意味着每一次读取IO口的数据前都要置1?[/quote] 1,退出while(1)→ 可以在while(1)最后加个break,退出while(tmp != 0xF0)→ 按键弹起后,IO口被拉成高电平,(tmp & 0xF0)结果为 0xF0,while 条件不再成立自动退出 2,IO口是双向IO口,不存在配置输入输出模式的说法,“向IO写1才能配置为输入模式”的说法是无中生有睁眼说瞎话的,读取IO口状态无需先置1。
jidumo 2017-08-02
  • 打赏
  • 举报
回复
引用 1 楼 jklinux 的回复:
其实你的问题可以分成两个独立的问题: 1.矩阵键盘区别出按键 2. 数码管的显示问题。 建议楼主先实现矩阵键盘的驱动先吧。 可参考矩阵键盘工作原理
好的,感谢回答
jidumo 2017-08-02
  • 打赏
  • 举报
回复
引用 8 楼 g62r83t27 的回复:
[quote=引用 6 楼 jidumo 的回复:] [quote=引用 4 楼 g62r83t27 的回复:] 首先我来理解你的4*4的矩阵键盘 1,按键按下对应IO口电平是低电平,按键弹起对应IO口电平为高 2,每个按键反馈给两个IO口,分别表示该按键所在的行与列 3,P3高4位对应4*4矩阵的4列,P3低四位对应4*4矩阵的4行,如下图,第一行第一列按键按下时,P3.1和P3.5对应低电平 while(temp!=0xf0)其实可以写成while(temp )这样好理解 然后来说说IO口输入输出模式,正好回答你的第二个问题。 1, 51单片机IO口为双向输入输出模式,意思是如下1.1和1.2: 1.1,给P3口赋值,表示P3口要输出高电平或低电平 如P3 = 0xFE;表示将P3.0拉低, P3.2-P3.7拉高 1.2,读P3口值,表示要读取P3口当前的状态,如temp = P3,意思是读取当前P3口状态。 这种状态是实时的,如第一行第一列按键按下,则temp的值应为11101110b,即0xEE,具体如下: 第一行第一列 对应的P3.0和P3.4的状态立即被拉低(按键将IO口与地短接),位值为0。 反之按键弹起则对应IO口状态立即被拉高(上拉电阻的功劳),位值为1。
当检测到有按键按下,程序运行到temp=P3,接着执行switch语句。退出switch语句后,回到第二个while(temp!=0xf0),在这个时候,程序怎么检测到下一次按键[/quote] 你的while(1)会不停地给P3赋值,P3 = 0小FE, 属于强制拉高,此时如果按键未弹起,强制拉高是无效的, 你的程序靠内两层循环来消除抖动实际上是多余的,调整delay(5); //延时消抖 这个值即可,更好的办法是消抖前后检测是否是同一个按键,不是的话不处理[/quote] 首先,非常感谢你的回答。我看懂了你的回复。但是我还有疑问,就是检测按键按下后,程序怎么退出while循环。第二个疑问:向IO口写1才能配置为输入模式,那是不是意味着每一次读取IO口的数据前都要置1?
xqhrs232 2017-07-30
  • 打赏
  • 举报
回复
距阵键盘还真从来没做过!
进击的生菜 2017-07-29
  • 打赏
  • 举报
回复
学习一下 我也遇到这个问题了
侦探蜡笔小新 2017-07-28
  • 打赏
  • 举报
回复
引用 6 楼 jidumo 的回复:
[quote=引用 4 楼 g62r83t27 的回复:] 首先我来理解你的4*4的矩阵键盘 1,按键按下对应IO口电平是低电平,按键弹起对应IO口电平为高 2,每个按键反馈给两个IO口,分别表示该按键所在的行与列 3,P3高4位对应4*4矩阵的4列,P3低四位对应4*4矩阵的4行,如下图,第一行第一列按键按下时,P3.1和P3.5对应低电平 while(temp!=0xf0)其实可以写成while(temp )这样好理解 然后来说说IO口输入输出模式,正好回答你的第二个问题。 1, 51单片机IO口为双向输入输出模式,意思是如下1.1和1.2: 1.1,给P3口赋值,表示P3口要输出高电平或低电平 如P3 = 0xFE;表示将P3.0拉低, P3.2-P3.7拉高 1.2,读P3口值,表示要读取P3口当前的状态,如temp = P3,意思是读取当前P3口状态。 这种状态是实时的,如第一行第一列按键按下,则temp的值应为11101110b,即0xEE,具体如下: 第一行第一列 对应的P3.0和P3.4的状态立即被拉低(按键将IO口与地短接),位值为0。 反之按键弹起则对应IO口状态立即被拉高(上拉电阻的功劳),位值为1。
当检测到有按键按下,程序运行到temp=P3,接着执行switch语句。退出switch语句后,回到第二个while(temp!=0xf0),在这个时候,程序怎么检测到下一次按键[/quote] 你的while(1)会不停地给P3赋值,P3 = 0小FE, 属于强制拉高,此时如果按键未弹起,强制拉高是无效的, 你的程序靠内两层循环来消除抖动实际上是多余的,调整delay(5); //延时消抖 这个值即可,更好的办法是消抖前后检测是否是同一个按键,不是的话不处理
侦探蜡笔小新 2017-07-27
  • 打赏
  • 举报
回复
更正下,第一行第一列按下,则P3.0和P3.4为低电平
侦探蜡笔小新 2017-07-27
  • 打赏
  • 举报
回复
首先我来理解你的4*4的矩阵键盘

1,按键按下对应IO口电平是低电平,按键弹起对应IO口电平为高

2,每个按键反馈给两个IO口,分别表示该按键所在的行与列

3,P3高4位对应4*4矩阵的4列,P3低四位对应4*4矩阵的4行,如下图,第一行第一列按键按下时,P3.1和P3.5对应低电平



然后来说说IO口输入输出模式,正好回答你的第二个问题。

1, 51单片机IO口为双向输入输出模式,意思是如下1.1和1.2:

1.1,给P3口赋值,表示P3口要输出高电平或低电平
如P3 = 0xFE;表示将P3.0拉低, P3.2-P3.7拉高

1.2,读P3口值,表示要读取P3口当前的状态,如temp = P3,意思是读取当前P3口状态。
这种状态是实时的,如第一行第一列按键按下,则temp的值应为11101110b,即0xEE,具体如下:
第一行第一列 对应的P3.0和P3.4的状态立即被拉低(按键将IO口与地短接),位值为0。
反之按键弹起则对应IO口状态立即被拉高(上拉电阻的功劳),位值为1。


worldy 2017-07-27
  • 打赏
  • 举报
回复
以4X4的矩阵键盘来说,一般 4根行线,4根列线,判断哪个键按下,其实就是判断哪根行线和列线连接!如何判断哪个行列线联通呢? 行线接输出引脚,列线接输入引脚,并使用一个电阻接地;如果没有按键,列线读到的全是0 行线轮流输入高电平,每根行数输入输出高电平后,读取列线,如果读到1,说明有按键按下,因为输出的哪根行线已知(单片机控制的),读到的哪个位为1也已知,因此,就可以判断出是哪个键按下
jidumo 2017-07-27
  • 打赏
  • 举报
回复
引用 4 楼 g62r83t27 的回复:
首先我来理解你的4*4的矩阵键盘 1,按键按下对应IO口电平是低电平,按键弹起对应IO口电平为高 2,每个按键反馈给两个IO口,分别表示该按键所在的行与列 3,P3高4位对应4*4矩阵的4列,P3低四位对应4*4矩阵的4行,如下图,第一行第一列按键按下时,P3.1和P3.5对应低电平 然后来说说IO口输入输出模式,正好回答你的第二个问题。 1, 51单片机IO口为双向输入输出模式,意思是如下1.1和1.2: 1.1,给P3口赋值,表示P3口要输出高电平或低电平 如P3 = 0xFE;表示将P3.0拉低, P3.2-P3.7拉高 1.2,读P3口值,表示要读取P3口当前的状态,如temp = P3,意思是读取当前P3口状态。 这种状态是实时的,如第一行第一列按键按下,则temp的值应为11101110b,即0xEE,具体如下: 第一行第一列 对应的P3.0和P3.4的状态立即被拉低(按键将IO口与地短接),位值为0。 反之按键弹起则对应IO口状态立即被拉高(上拉电阻的功劳),位值为1。
当检测到有按键按下,程序运行到temp=P3,接着执行switch语句。退出switch语句后,回到第二个while(temp!=0xf0),在这个时候,程序怎么检测到下一次按键
int_Paul 2017-07-26
  • 打赏
  • 举报
回复
楼主如果还有什么不懂得,加我QQ794451358
int_Paul 2017-07-26
  • 打赏
  • 举报
回复
这个问题其实就是你没搞清楚,矩阵键盘是怎么工作的,你现在这段程序的意思是,你的矩阵键盘只用了第一行,行线是P3的高4位,列线是P3口的最后一位。首先我给你说一下矩阵键盘是怎么检测的:首先,把它的列线置0,检测行线,如果按键按下,那么对应按键的行线会被拉低。然后回到你的程序,首先程序把P3口的末位置0,就是P3=0xfe,此时,判断高四位的状态,就是判断P3&0xf0是否等于0xf0,如果相等,证明高四位没有被拉低,按键没有按下,如果不等于0xf0,那么证明有按键按下,然后延时消抖,在判断一次之后,把P3的状态赋值给temp,如果P3=0xee(11101110),表示高四位的末位被拉低,就是说高四位的末位对应的行线被拉低了,那么找出该行线对应的按键,就可以判断该按键被按下
jklinux 2017-07-25
  • 打赏
  • 举报
回复
其实你的问题可以分成两个独立的问题: 1.矩阵键盘区别出按键 2. 数码管的显示问题。


建议楼主先实现矩阵键盘的驱动先吧。
可参考矩阵键盘工作原理

27,375

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 单片机/工控
社区管理员
  • 单片机/工控社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧