使用行列扫描法判断是否有按键按下以及哪个按键按下。
假设m行n列有一个按键S按下。
先让高4位为0,低4位为1,即P1=0000 1111。那么由于S的按下,按键两端的导线接通,低4位必有一个端口检测到低电平。芯片便可以判断出第n列有一个按键按下。
然后令高4位为1,低4位为0,即P1=1111 0000。那么由于S的按下,按键两端的导线接通,高4位必有一个端口检测到低电平。芯片便可以判断出第m行有一个按键按下。
由此便可以知道是m行n列有一个按键S按下。
序号=m*4+n
#include"reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
void delay(u16 s);
int key(void); //key返回按键的序号,0-15
unsigned char num[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0xff/*0xff表示全亮*/};
u8 line,row,number=16;
u8 a=0;
sbit LSA=P2^2;
sbit LSB=P2^3;
sbit LSC=P2^4;
void main()
{
LSA=1;LSB=1;LSC=1;//选中最高位的数码管显示,不过单片机默认高电平,这3条不要也罢
while(1)
{
P0=num[key()];
}
}
void delay(u16 s) //延时函数
{
while(s--);
}
int key(void)
{
P1=0x0f;//0000 1111
if(P1!=0x0f)
{
delay(1000);
if(P1!=0x0f)
{
switch(P1) //判断是哪一列按下
{
case 0x07:line=0;break;
case 0x0b:line=1;break;
case 0x0d:line=2;break;
case 0x0e:line=3;break;
}
}
P1=0xf0;
if(P1!=0xf0)
{
switch(P1) //判断是哪一行按下
{
case 0x70:row=0;break;
case 0xb0:row=1;break;
case 0xd0:row=2;break;
case 0xe0:row=3;break;
}
}
number=row*4+line;
}
while((a<50)&&(P1!=0xf0))
{
delay(100);
a++;
}
return number;//如果有按下,number的值就是按下的值;如果没有按下,number在上面被初始化为16,即全亮,单片机在没有按键按下时就是全亮
}