矩阵键盘遇见的问题

 

#include
#define uchar unsigned char  //数据类型的宏定义
#define uint  unsigned int	 //数据类型的宏定义
sbit BEEP = P3^6; //蜂鸣器控制端口P36 
unsigned char table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xBF}; 
	 //共阳数码管显示字型码数组

void delay(void) 
{ 
unsigned char i,j; 
for(i=0;i<20;i++) 
for(j=0;j<250;j++); 
}
/* 延时子程序*/

void  delay1(uchar x)
{ uchar j;
    while((x--)!=0)
    { for(j=0;j<125;j++)
         {;}
    }
}
//--------------------------------------------------
 //--------------------------------------------------
void delay0(uchar x)    //x*0.14MS
{
 unsigned char i;
  while(x--)
 {
  for (i = 0; i<13; i++) {}
 }
}



/*********************************************************/
void beep()		//蜂鸣器响一声函数
{
  unsigned char i;
  for (i=0;i<100;i++)
   {
   delay0(4);
   BEEP=!BEEP;       //BEEP取反
   } 
   BEEP=1;           //关闭蜂鸣器
   delay1(250);       //延时     
}

void display(unsigned char i) 
{ 
P2=0x7f;  //选通最有端的数码管显示
P0=table[i];   //显示i参数传来的字型码
} 

void keyscan(void) 
{
unsigned char temp; 

//扫描第一行 
P1=0xfe; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
delay(); 
P1=0xfe; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
beep();
switch(temp) 
{ 
case(0xe0):display(0);break; 
case(0xd0):display(1);break; 
case(0xb0):display(2);break; 
case(0x70):display(3);break; 
} 
} 
} 

//扫描第二行 
P1=0xfd; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
delay(); 
P1=0xfd; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
beep();
switch(temp) 
{ 
case(0xe0):display(4);break; 
case(0xd0):display(5);break; 
case(0xb0):display(6);break; 
case(0x70):display(7);break; 
} 
} 
} 

//扫描第三行 
P1=0xfb; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 

delay(); 
P1=0xfb; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
beep();
switch(temp) 	
{ 
case(0xe0):display(8);break; 
case(0xd0):display(9);break; 
case(0xb0):display(10);break; 
case(0x70):display(11);break; 
} 
} 
} 

//扫描第四行 
P1=0xf7; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
delay(); 
P1=0xf7; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
beep();
switch(temp) 
{
case(0xe0):display(12);break; 
case(0xd0):display(13);break; 
case(0xb0):display(14);break; 
case(0x70):display(15);break; 
} 
} 
} 
}
 
void main(void) 
{ 
display(16); //初始显示 -
while(1) 
{ 
keyscan(); //执行按键扫描程序
} 
}


这上面是K:\锐志电子资料\RZ-51V20 配套软件及资料\RZ-51V20 PDF配套教程\配套教程实例\RZ-SL7 4X4矩阵键盘实验 的整个代码,但对红色的部分不理解。
P1=0xfe; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
{ 
delay(); 
P1=0xfe; 
temp=P1; 
temp&=0xf0; 
if(temp!=0xf0) 
上面将P1赋了值,然后马上用temp取值。疑问:这时temp那岂不是99%还是0xfe而不是按键后改变的值。(这两条语句之中大概几条汇编指令吧,这么短的时间按键的效果怎么就这么快就反映到IO口上?如果说是电流的传递速度的话(貌似线与(一个老副教授如是说这是线与的关系(坑人啊)) 还要什么什么门进行处理,这个处理放在芯片内部?那岂不是硬件的响应时间再次被托慢了?),那么?)我认为应该加个延时。不加延时根本就不会响应,但是这个程序原封不同的编译,然后烧到板上确实能够准确响应按键运行。这又是为何?难道类似于ARM中的IDR(输入缓冲寄存器)和ODR(输出缓冲寄存器)?赋值与接收 是放在不同的寄存器中?而P1 = 0xfe 只是向其输出寄存器中赋值? Temp = P1是从其输入缓冲器中取值????内部结构到底是怎么样呢??(一个IO口配套的寄存器 又是怎么协调工作的呢?)
问题得以解决,听另一个年轻老师说这里并不是 线与的关系,线与 常用在总线上,是得益于一个单片机电路图,若按下为0后 不管你赋值什么都是不起作用的,因为一端已经接地,你把高电平接上,端口收到的还是低电平。所以这代码是没有问题的,不用加什么延时,相关电路图 待会儿 传上。
看电路图只有个锁存器,没有什么缓存器。

你可能感兴趣的:(单片机)