以前学习51单片机,总想着电路设计,所以程序里也体现了器件的电气连接。这是一个4x4的小键盘,也是用模拟软件仿真的。
#include <reg51.h>
//p1.0~p1.3用作输出,P1.4~ P1.7用做输入,接上拉电阻;
//列号码: P1.4 P1.5 P1.6 P1.7
//行号码P1.0: '3' '2' '1' '0'
//行号码P1.1: '7' '6' '5' '4'
//行号码P1.2: 'B' 'A' '9' '8'
//行号码P1.3: 'F' 'E' 'D' 'C'
code keyboard[4][4]=\
{ {'3','2','1','0'},\
{'7','6','5','4'},\
{'B','A','9','8'},\
{'F','E','D','C'}
};
//函数功能:延时400us@12MHz晶振;
void delay_ms()
{ unsigned char i;
for(i=200;i>0;i--)
{}
}
//p1.0~p1.3用作输出,P1.4~ P1.7用做输入,接上拉电阻;
//列号码: P1.4 P1.5 P1.6 P1.7
//行号码P1.0: 3 2 1 0
//行号码P1.1: 7 6 5 4
//行号码P1.2: 11 10 9 8
//行号码P1.3: 15 14 13 12
//函数功能:从键盘读取一个值,便返回该值,若没有读到则返回0;
unsigned char scan_keyboard()
{ unsigned char col,row,key_value;
key_value=0;
P1=0xf0; //先将P1口的低4位输出0;
if( (P1&0xf0)!=0xf0 ) //若读P1口的值不为0xf0,则表示有键被按下;
{ delay_ms(); //延时,消抖;
if( (P1&0xf0)!=0xf0 ) //若读P1口的值不为0xf0,则表示有键被按下;
{ row=0xfe;
while( (row&0x10)!=0 )
//当row到达0xef时,即扫描完4行,没有发现有键按下,可能是键盘误动作;
{ P1=row;
//P1口输出:0xfe(选择第1行,P1.0=0),0xfd
//(选择第2行P1.1=0),0xfb(选择第3行P1.2=0),0xf7(选择第4行P1.3=0);
if( (P1&0xf0)!=0xf0 ) //若读P1口的值不为0xf0,则表示有键被按下;
{ col=(P1&0xf0)|0x0f;
//将P1口高4位的值保留,将低4位置1,保存到col中;
//为了查表,下面对row和col进行解码;
if(row==0xfe) row=0;
else if(row==0xfd) row=1;
else if(row==0xfb) row=2;
else if(row==0xf7) row=3;
else row=4;
if(col==0xef) col=0;
else if(col==0xdf) col=1;
else if(col==0xbf) col=2;
else if(col==0x7f) col=3;
else col=4;
if( (row<4)&&(col<4) )
{ key_value=keyboard[row][col];
//查表,将读到的ASCii码值保存到key_value中;
break; //退出while循环;
}
}
else row=(row<<1)|0x01;
//将row的值左移1位,同时将最低位补1,从0xfe>0xfd>0xfb>0xf7>0xef进行改变
}
}
}
return(key_value); //返回读到的键盘值,没有读到,则返回0;
}
void main(void)
{
unsigned char key_value1;
for(;;)
{
key_value1= scan_keyboard(); //从键盘读取一个值,便返回该值,若没有读到则返回0;
delay_ms(); //延时400us@12MHz晶振;
}
}