要求:设密码锁的正确密码为8位数字01234567。16个矩阵键盘按键分别对应0-F,按下每一个按键在8位共阴数码管上从左到右依次显示刚才所按下的数字。当按下8个数字后,再按下任意一个按键实现将所按下的8个数字与正确密码对比,如若密码一致,数码管上显示oPEn,如若密码不正确,数码管上显示Err。密码正确或错误后再按下按键重新显示按下的数字。实验原理图如图1:
<center>图1 矩阵键盘按键原理图</center>
代码如下:
#include <reg51.h>
#include <intrins.h>
sbit LATCH1=P2^2;
sbit LATCH2=P2^3;
unsigned char code DuanMa[]= {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
unsigned char code WeiMa[]= {0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char KeyScan(void);
unsigned char KeyPro(void);
unsigned char TempData[8] = {0,0,0,0,0,0,0,0};
unsigned char password[8] = {0,1,2,3,4,5,6,7};
unsigned char password1[8] = {0,1,2,3,4,5,6,7};
void Display(void);
int k = 0;
int flag;
int j;
void delay()
{
int y;
for(y=300;y>0;y--);
}
void main()
{
TMOD = 0x01;
TR0 = 1;
EA = 1;
ET0 = 1;
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
while (1)
{
flag = KeyPro();
if(flag != 0xff)
{
if (k < 8)
{
password1[k] = flag;
TempData[k++] = DuanMa[flag];
}
else if (k == 8)
{
int flg = 1;
for (j = 0; j < 8;j++)
{
if (password1[j] != password[j])
{
flg = 0;
}
}
if (!flg)
{
TempData[0] = 0x79;
TempData[1] = 0x50;
TempData[2] = 0x50;
TempData[3] = 0;
TempData[4] = 0;
TempData[5] = 0;
TempData[6] = 0;
TempData[7] = 0;
}
else
{
TempData[0] = 0x5c;
TempData[1] = 0x73;
TempData[2] = 0x79;
TempData[3] = 0x54;
TempData[4] = 0;
TempData[5] = 0;
TempData[6] = 0;
TempData[7] = 0;
}
k++;
}
else
{
k =0;
for (j = 0; j < 8;j++)
{
TempData[j] = 0;
}
}
}
}
}
void inti0() interrupt 1
{
TH0 = (65536 - 1000) / 256;
TL0 = (65536 - 1000) % 256;
Display();
}
unsigned char KeyScan(void)
//键盘扫描函数
{
unsigned char temp1,temp2;
//行列值中间变量
P1=0x0f; //列线输出全为0,检测行线
if(P1!=0x0f) //先检测有无按键按下
{delay (); //延时去抖几ms
if(P1!=0x0f)
{
temp1 = P1;
P1 = 0xf0;
temp2 = P1;
while (P1 != 0xf0);
return(temp1+temp2);
//键盘最后组合特征值
}
}return(0xff); //返回该值
}
unsigned char KeyPro(void)
{ switch(KeyScan())
{case 0x7e:return 0;break;//0 按下相应的键显示相对应的码值
case 0xbe:return 1;break;//1
case 0xde:return 2;break;//2
case 0xee:return 3;break;//3
case 0x7d:return 4;break;//4
case 0xbd:return 5;break;//5
case 0xdd:return 6;break;//6
case 0xed:return 7;break;//7
case 0x7b:return 8;break;//8
case 0xbb:return 9;break;//9
case 0xdb:return 10;break;//a
case 0xeb:return 11;break;//b
case 0x77:return 12;break;//c
case 0xb7:return 13;break;//d
case 0xd7:return 14;break;//e
case 0xe7:return 15;break;//f
default:return 0xff;break;}
}
void Display(void)
{ static unsigned char i=0;
P0=0; //清空数据,防止有交替重影
LATCH1=1; //LATCH1=P2.2,段锁存
LATCH1=0;
P0 =WeiMa[i]; //取位码
LATCH1=1; // LATCH2=P2.3位锁存
LATCH1=0;
P0=TempData[i]; //取显示数据对应的段码
LATCH2=1; //段锁存
LATCH2=0;
i++;
if(i==8)
i=0;
}