求助关于矩阵键盘点亮LED灯

aduwu_para 2011-10-10 08:39:39
模仿wang1jin单片机教程中关于矩阵键盘点亮LED灯的教程没有成功。原教程中是一个4x4的矩阵键盘,而我的开发板是一个3x4的矩阵键盘,键盘电路图如图所示:

我将矩阵键盘引脚与P2口相连。该历程中,利用2组P3口返回值定位按下的键,继而点亮LED灯。我编写的程序如下:
#include<reg51.h>

sbit LED1 = P3^0;
sbit LED2 = P3^1;
sbit LED3 = P3^2;
sbit LED4 = P3^3;
sbit LED5 = P3^4;
sbit LED6 = P3^5;
sbit LED7 = P3^6;
sbit LED8 = P3^7;

void Delay(unsigned int i);
void Key(void);

void main()
{
while(1)
{
Key();
}
}

void Key(void)
{
unsigned char i = 0;
unsigned char j = 0;
unsigned char k = 0;
unsigned char KEY_Value = 0;

P2 = 0x0F;
i = P2;
if(i != P2)
{
Delay(1000); // 延时消抖
P2 = 0x0F; // 输入0xFF
i = P2; // 返回P2值
if(i != P2) // 监测是否有按键按下
{
P2 = 0x0F;
i = P2; // 返回值1
P2 = 0x70;
j = P2; // 返回值2
P2 = 0x7F;
k = i|j; // 两返回值按位或得到定位键盘的值
switch(k) // 定位按下的键盘
{
case 0x37:
{
KEY_Value = 1;
break;
}
case 0x3B:
{
KEY_Value = 2;
break;
}
case 0x3D:
{
KEY_Value = 3;
break;
}
case 0x3E:
{
KEY_Value = 4;
break;
}
case 0x57:
{
KEY_Value = 5;
break;
}
case 0x5B:
{
KEY_Value = 6;
break;
}
case 0x5D:
{
KEY_Value = 7;
break;
}
case 0x5E:
{
KEY_Value = 8;
break;
}
case 0x67:
{
KEY_Value = 9;
break;
}
case 0x6B:
{
KEY_Value = 10;
break;
}
case 0x6D:
{
KEY_Value = 11;
break;
}
case 0x6E:
{
KEY_Value = 12;
break;
}
}
P2 = 0x0F; // 判断键盘是否松开
i = P2;
P2 = 0x70;
j = P2;
P2 = 0x7F;
k = i|j;
while(k != 0x7F)
{
P2 = 0x0F;
i = P2;
P2 = 0x70;
j = P2;
P2 = 0x7F;
k = i|j;
}
}
}
switch(KEY_Value) // 利用不同的键盘点亮/熄灭不同的LED灯
{
case 1: LED1 = ~LED1;break;
case 2: LED2 = ~LED2;break;
case 3: LED3 = ~LED3;break;
case 4: LED4 = ~LED4;break;
case 5: LED5 = ~LED5;break;
case 6: LED6 = ~LED6;break;
case 7: LED7 = ~LED7;break;
case 8: LED8 = ~LED8;break;
case 9: LED1 = ~LED1;break;
case 10: LED2 = ~LED2;break;
case 11: LED3 = ~LED3;break;
case 12: LED4 = ~LED4;break;
}
}

void Delay(unsigned int i)
{
while(-- i);
}

利用矩阵键盘推导返回值过程如图:

请大神帮忙找一下错误吧,我自己想了下,觉得可能是图中P-10口悬空后有问题,我在上面的推导过程中一直将P27设置为0,不知道是不是这个问题?
...全文
1121 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
新的飞跃 2013-08-16
  • 打赏
  • 举报
回复
怎么我试验 不行???是不是 还有错啊。。。
aduwu_para 2011-10-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sxper 的回复:]
if(i != P2) // 监测是否有按键按下 假设 有按下 键值是00001101 s1按下
{
P2 = 0x0F; 无效 因为被按下 p2=00001101
i = P2; // 返回值1无效 因为被按下 p2=00001101

P2 = 0x70; 无效 因为被按下 p2=00001101

j = P2; // 返回值2无效 因为被按下 ……
[/Quote]

经改正if语句判断条件应该为(i != 0x0F)
验证成功,非常感谢
aduwu_para 2011-10-11
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sxper 的回复:]
if(i != P2) // 监测是否有按键按下 假设 有按下 键值是00001101 s1按下
{
P2 = 0x0F; 无效 因为被按下 p2=00001101
i = P2; // 返回值1无效 因为被按下 p2=00001101

P2 = 0x70; 无效 因为被按下 p2=00001101

j = P2; // 返回值2无效 因为被按下 ……
[/Quote]

经改正if语句判断条件应该为(i != 0x0F)
验证成功,非常感谢
aduwu_para 2011-10-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 peasant_lee 的回复:]
楼主,我看了一下code,我倒有个建议,你可以将P1.1 1.2 1.3 1.4分别定义,然后每配置一次电平,做一次扫描动作,都将这个分别赋值或者读取。那这样程序架构很清晰,而且也容易排查问题。
[/Quote]
谢谢,这个方法我也用过了,就是想试验不同的方法
sxper 2011-10-10
  • 打赏
  • 举报
回复
if(i != P2) // 监测是否有按键按下 假设 有按下 键值是00001101 s1按下
{
P2 = 0x0F; 无效 因为被按下 p2=00001101
i = P2; // 返回值1无效 因为被按下 p2=00001101

P2 = 0x70; 无效 因为被按下 p2=00001101

j = P2; // 返回值2无效 因为被按下 p2=00001101

P2 = 0x7F;无效 因为被按下 p2=00001101

k = i|j; // 无效 因为被按下 p2=00001101
Peasant_Lee 2011-10-10
  • 打赏
  • 举报
回复
楼主,我看了一下code,我倒有个建议,你可以将P1.1 1.2 1.3 1.4分别定义,然后每配置一次电平,做一次扫描动作,都将这个分别赋值或者读取。那这样程序架构很清晰,而且也容易排查问题。

27,383

社区成员

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

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