单片机矩阵键盘程序求解释和修正!

用的郭天祥的程序,顺序按下键盘后,显示0~F,但是编译后数码管一个也不亮。

我对程序有点疑问:P3=0xfe”将第一行线设置为低电平后,立即又令temp=P3;那么temp不也是变成0xfe?那对应一个键被按下的那一个语句在哪儿呢?(书中说就是temp,但是temp被赋值为P3,但P3已被赋值为0xfe用来检测)
还有P3=0xfe,这是通过程序将P3.0设置成0,那跟用一个导线将P3.0接地有区别吗?

硬件没问题,程序如下:

#include<STC12C5A60S2.h>
char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x00,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delayms(int xms)
{
int i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(char num)
{
P1=table[num]; //段选数据
}
void matrixkeyscan()
{
char temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
delayms(10);
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)
{
temp=P3;
switch(temp)
{
case 0xee:
key=0;
break;
case 0xde:
key=1;
break;
case 0xbe:
key=2;
break;
case 0x7e:
key=3;
break;
}
while(temp!=0xf0)
{
temp=P3;
temp=temp&0xf0;
}
display(key);
}
}
P3=0xfd;
{......};
P3=0xfb:
{......};
P3=0xf7;
{......};

void main()
{
P0M1 = 0x00;//推挽输出的定义
P0M0 = 0x0f;//推挽输出的定义
P0=0x0f;
while(1)
{
matrixkeyscan();//不停调用键盘扫描程序
}
}
程序有点长不能全复制上去,中途对于P3的4次检测只显示了第一个“P3=0xfe”将第一行线设置为低电平,后面三行的检测跟这个一样。
有TX有单片机在身边的能试一下帮我解决这个问题吗?

没有硬件电路,单从程序来看应该没错。我加了注释,你可以参考下。
#include<STC12C5A60S2.h>
char code table[]={
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x00,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
void delayms(int xms)
{
int i,j;
for(i=xms;i>0;i--) //i=xms即延时约xms毫秒
for(j=110;j>0;j--);
}
void display(char num)
{
P1=table[num]; //段选数据
}
void matrixkeyscan()
{
char temp,key;
P3=0xfe;
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//说明有按键按下
{
delayms(10);//延时,去抖动
temp=P3;
temp=temp&0xf0;
if(temp!=0xf0)//说明按键被持续按下
{
temp=P3;//记录P3口状态
switch(temp)//根据现在的状态判断哪个按键被按下
{
case 0xee: //p3^4被按下
key=0;
break;
case 0xde: //p3^5
key=1;
break;
case 0xbe://p3^6
key=2;
break;
case 0x7e://p3^7
key=3;
break;
}
while(temp!=0xf0)//按键松开之后跳出循环
{
temp=P3;
temp=temp&0xf0;
}
display(key);//显示
}
}
P3=0xfd;
{......};
P3=0xfb:
{......};
P3=0xf7;
{......};

void main()
{
P0M1 = 0x00;//推挽输出的定义
P0M0 = 0x0f;//推挽输出的定义
P0=0x0f;
while(1)
{
matrixkeyscan();//不停调用键盘扫描程序
}
}
温馨提示:答案为网友推荐,仅供参考
第1个回答  2013-09-26
你这个程序适用于普通51单片机,STC12C5A60S2由于是1T模式单片机,所以速度太快,你需要修改延时程序和部分IO口操作的程序,否则工作是不太正常的。为了验证,你可以换一片普通单片机试试。
第2个回答  推荐于2017-09-02
#include<reg52.h>//P0口为数据命令接口 可更改
#define uint unsigned int
#define uchar unsigned char
sbit jian0=P1^0;//键盘扫描接口
sbit jian1=P1^1;//键盘扫描接口
sbit jian2=P1^2;//键盘扫描接口
sbit jian3=P1^3;//键盘扫描接口
sbit jian4=P1^4;//键值分辨接口
sbit jian5=P1^5;//键值分辨接口
sbit jian6=P1^6;//键值分辨接口
sbit jian7=P1^7;//键值分辨接口
//write_com(0x18);//整屏左移可用
sbit LCD_EN=P2^3;//接口
sbit LCD_RW=P2^5;//接口
sbit LCD_RS=P2^4;//接口
uchar code table[]="YuanJia XiaoYun";//显示字样
uchar code table1[]="--zhi lian--";//显示字样
uchar num;
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com)//写指令小程序 读指令时需要更改
{
LCD_RS=0;
LCD_RW=0;
P0=com;
delay(5);
LCD_EN=1;
delay(5);
LCD_EN=0;
LCD_RS=1;
}

void write_data(uchar date)//写数据小程序 读数据时需要更改
{
LCD_RS=1;
LCD_RW=0;
P0=date;
delay(5);
LCD_EN=1;
delay(5);
LCD_EN=0;
LCD_RS=0;
}
void LCD_jian1()
{
write_data('s');
delay(10);
}
void LCD_jian2()
{
write_data('U');
delay(10);
}
void LCD_jian3()
{
write_data('N');
delay(10);
}
void LCD_jian4()
{
write_data('Y');
delay(10);
}
void LCD_jian5()
{
write_data('U');
delay(10);
}
void LCD_jian6()
{
write_data('A');
delay(10);
}
void LCD_jian7()
{
write_data('N');
delay(10);
}
void LCD_jian8()
{
write_data('J');
delay(10);
}
void LCD_jian9()
{
write_data('I');
delay(10);
}
void LCD_jian10()
{
write_data('A');
delay(10);
}
void LCD_jian11()
{
write_data('D');
delay(10);
}
void LCD_jian12()
{
write_data('I');
delay(10);
}
void LCD_jian13()
{
write_data('A');
delay(10);
}
void LCD_jian14()
{
write_com(0x01);
delay(10);
}
void LCD_jian15()
{

write_com(0xc0+0x12);
delay(10);
}
void LCD_jian16()
{
write_com(0x12);
delay(10);
}
void key44()//键值分辨
{
if(jian4==0)
{
if(jian0==0){LCD_jian1();}
if(jian1==0){LCD_jian2();}
if(jian2==0){LCD_jian3();}
if(jian3==0){LCD_jian4();}
delay(300);//消抖
}

if(jian5==0)
{
if(jian0==0){LCD_jian5();}
else if(jian1==0){LCD_jian6();}
else if(jian2==0){LCD_jian7();}
else if(jian3==0){LCD_jian8();}
delay(300);//消抖
}

if(jian6==0)
{
if(jian0==0){LCD_jian9();}
else if(jian1==0){LCD_jian10();}
else if(jian2==0){LCD_jian11();}
else if(jian3==0){LCD_jian12();}
delay(300);//消抖
}

if(jian7==0)
{
if(jian0==0){LCD_jian13();}
else if(jian1==0){LCD_jian14();}
else if(jian2==0){LCD_jian15();}
else if(jian3==0){LCD_jian16();}
delay(300);//消抖
}
}
void jianpan44()//键扫主程序
{
P1=0xff;
jian0=0;
key44();
delay(3);
P1=0xff;
jian1=0;
key44();
delay(3);
P1=0xff;
jian2=0;
key44();
delay(3);
P1=0xff;
jian3=0;
key44();
delay(3);
P1=0xff;
}
void init()
{
LCD_RW=0;
LCD_EN=0;
write_com(0x38);//16*2显示,8位数据接口
write_com(0x0f);//开显示,显示光标,光标闪烁
write_com(0x06);//当读或者写一个字符后,指针加一,光标加一。
write_com(0x01);//清屏
write_com(0x80);//设置显示位置 可变可更改
}
void main()
{
init();
for(num=0;num<8;num++)
{
write_data(table[num]);
delay(10);
}
write_com(0x80+0x2c);
for(num=0;num<10;num++)
{
write_data(table1[num]);
delay(10);
}
delay(3000);
write_com(0x01);//清屏
while(1)
{
jianpan44();
}
}