一个51单片机矩阵键盘控制发光二极管的问题。

要求是按下一个键后,发光二极管点亮,再按一下熄灭,键盘为矩阵键盘,P1口接矩阵键盘,P2口接发光二极管(共阳极),控制8个LED。自己写了一个程序,但达不到预想的效果,按一下点亮,再按一下并不熄灭,程序如下,求大神指出错误。。

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
sbit D1=P2^7;
sbit D2=P2^6;
sbit D3=P2^5;
sbit D4=P2^4;
sbit D5=P2^3;
sbit D6=P2^2;
sbit D7=P2^1;
sbit D8=P2^0;
uchar num,temp,LED;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
uchar keyscan();
void main()
{
while(1)
{
LED=keyscan();
switch(LED)
{
case 1:D1=!D1;LED=0;
break;
case 2:D2=!D2;LED=0;
break;
case 3:D3=!D3;LED=0;
break;
case 4:D4=!D4;LED=0;
break;
case 5:D5=!D5;LED=0;
break;
case 6:D6=!D6;LED=0;
break;
case 7:D7=!D7;LED=0;
break;
case 8:D8=!D8;LED=0;
break;
}
}
}
uchar keyscan()
{
P1=0xfe;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xee:num=1;
break;
case 0xde:num=2;
break;
case 0xbe:num=3;
break;
case 0x7e:num=4;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
P1=0xfd;
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
delay(5);
temp=P1;
temp=temp&0xf0;
while(temp!=0xf0)
{
temp=P1;
switch(temp)
{
case 0xed:num=5;
break;
case 0xdd:num=6;
break;
case 0xbd:num=7;
break;
case 0x7d:num=8;
break;
}
while(temp!=0xf0)
{
temp=P1;
temp=temp&0xf0;
}
}
}
return num;
}

第1个回答  2013-04-23
如果用的是Keil编译器,你的位取反表达式是错误的,请参考以下程序段改动:
while(1)
{
LED = 0;//将这句安排在这里,原case后面的那些LED = 0;就可以全部不要了。
LED=keyscan();
switch(LED)

{
case 1:D1=~D1;
break;
case 2:D2=~D2;
break;
case 3:D3=~D3;
break;
case 4:D4=~D4;
break;
case 5:D5=~D5;
break;
case 6:D6=~D6;
break;
case 7:D7=~D7;
break;
case 8:D8=~D8;
break;
}
}本回答被网友采纳
第2个回答  2019-09-27
#include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器

typedef unsigned int u16; //对数据类型进行声明定义
typedef unsigned char u8;

#define GPIO_DIG P0
#define GPIO_KEY P1

sbit LSA=P3^2;
sbit LSB=P3^3;
sbit LSC=P3^4;

sbit led0 = P2^0;
sbit led1 = P2^1;
sbit led2 = P2^2;
sbit led3 = P2^3;
sbit led4 = P2^4;

sbit led5 = P2^5;
sbit led6 = P2^6;
sbit led7 = P2^7;

u8 KeyValue; //用来存放读取到的键值

u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值

void delay(u16 i)
{
while(i--);
}

void KeyDown(void)
{
char a=0;
GPIO_KEY=0x0f;
if(GPIO_KEY!=0x0f)//读取按键是否按下
{
delay(1000);//延时10ms进行消抖
if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
{
//测试列
GPIO_KEY=0X0F;
switch(GPIO_KEY)
{
case(0X07): KeyValue=0;break;
case(0X0b): KeyValue=1;break;
case(0X0d): KeyValue=2;break;
case(0X0e): KeyValue=3;break;
}
//测试行
GPIO_KEY=0XF0;
switch(GPIO_KEY)
{
case(0X70): KeyValue=KeyValue;break;
case(0Xb0): KeyValue=KeyValue+4;break;
case(0Xd0): KeyValue=KeyValue+8;break;
case(0Xe0): KeyValue=KeyValue+12;break;
}
while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
{
delay(1000);
a++;
}
switch(KeyValue){
case(0): led0= ~led0 ;break;
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): led0= ~led0 ;break;
case(9): led1= ~led1 ;break;
case(10): led2= ~led2 ;break;
case(11): led3= ~led3 ;break;
case(12): led4= ~led4 ;break;
case(13): led5= ~led5 ;break;
case(14): led6= ~led6 ;break;
case(15): led7= ~led7 ;break;

}
}
}
}

void main()
{ P2 = 0000;
LSA=0; //给一个数码管提供位选
LSB=0;
LSC=0;
while(1)
{
KeyDown(); //按键判断函数
GPIO_DIG=smgduan[KeyValue]; //

}
}