看到电影里面的保险箱用到的密码锁,于是心血来潮动手做了一个简单的密码锁,其有3次输入的机会,全错的话便进入死循环,一直警报,任何操作都无效,除了复位操作哈。所需素材:51单片机、1602液晶、蜂鸣器、按键、继电器、三极管、电磁锁等。话不多说,直接上代码:
#include<reg52.h>#define ucharunsigned char
#define uintunsigned int
#define LCD1602_DATAPINS P0
#define MbtrixButtons P1
#define size 4 //设置密码的位数 char possword[size]={1,2,3,4};//密码,自行设定,可以设置更多位密码
char check[size]; //寄存按键后的密码
char KeyValue,j=0;
char title[]="shu ru mi ma :";
char tishi1[]="mi ma cuo wu !!!";
char tishi2[]="ji hui : ";
char tishi3[]="mi ma zheng que!";
char tishi4[]=" suo yi kai ";
char tishi5[]=" jin bao";
char arr[]="0123456789"; uint xdata num=0,num1=0,num3=3,time=4,sleep=20;sbit relay=P2^0; //继电器输入端,用来控制电磁锁
sbit confirm=P2^1; //确认密码按键
sbit delet=P2^2; //删除键,清零
sbit blak=P2^3; //使单片机休眠时液晶屏熄灭,接液晶的背光源正极,最好用三极管驱动
sbit buzz=P2^4; //蜂鸣器
sbit RW=P2^5; //读写选择端
sbit RS=P2^6; //数据命令选择端
sbit E=P2^7; //使能端void Delay1ms(uinti) //延时,误差 0us
{uchar j;for (; i>0; i--)for (j=200;j>0;j--);
}void LcdWriteCom(uchar com) //写入命令
{E = 0; //使能RS = 0; //选择发送命令RW = 0; //选择写入LCD1602_DATAPINS = com; //放入命令Delay1ms(1); //等待数据稳定E = 1; //写入时序Delay1ms(5); //保持时间E = 0;
} void LcdWriteData(uchar dat) //写入数据
{E = 0; //使能清零RS = 1; //选择输入数据RW = 0; //选择写 LCD1602_DATAPINS = dat; //写入数Delay1ms(1);E = 1; //写入时序Delay1ms(5); //保持时间E = 0;
}void LcdInit() //LCD初始化子程序
{LcdWriteCom(0x38); //开显示LcdWriteCom(0x0f); //开显示不显示光标LcdWriteCom(0x06); //写一个指针加1LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //设置数据指针起点
}void delay(uint i)
{while(i--);
}void KeyDown() //矩阵按键
{char a=0;MbtrixButtons=0x0f;if(MbtrixButtons!=0x0f) //读取按键是否按下{delay(1000); //延时10ms进行消抖if(MbtrixButtons!=0x0f) //再次检测键盘是否按下{ //测试列MbtrixButtons=0X0F;switch(MbtrixButtons){case(0X07): KeyValue=0;break;case(0X0b): KeyValue=1;break;case(0X0d): KeyValue=2;break;case(0X0e): KeyValue=3;break;}//测试行MbtrixButtons=0XF0;switch(MbtrixButtons){case(0X70): KeyValue=KeyValue;break;case(0Xb0): KeyValue=KeyValue+4;break;case(0Xd0): KeyValue=KeyValue+8;break;case(0Xe0): KeyValue=KeyValue+12;break;}while((a<500)&&(MbtrixButtons!=0xf0)) //检测按键松手检测{delay(1000);a++;} LcdWriteData(arr[KeyValue]); }check[j]=KeyValue; //将按下的数值赋给checkj++;if(j>size-1) //当按下size-1位数后再按只改变check[size-1]的值j=size-1;num1=0; }
}void confirmkey() //确认按键
{ int i,k=1; if(sizeof(check)/sizeof(char)==size) //判断寄存数组的密码位数与设定的密码位数是否相同{for(i=0;i<size;i++){if(possword[i]==check[i]) //判断寄存数组的密码与设定的密码是否相等{k++; }else{break;}if(k==size) // 如果寄存数组中每个数都与设定的密码相等,就开锁{relay=1;for(i=0;i<size;i++) // 开锁后,将寄存数组清零{check[i]=0;}LcdWriteCom(0x01); //清屏LcdWriteCom(0x80); //显示液晶屏第一行for(i=0;i<17;i++)LcdWriteData(tishi3[i]);LcdWriteCom(0x80+0x40); //显示液晶屏第二行for(i=0;i<15;i++)LcdWriteData(tishi4[i]);LcdWriteCom(0x0c);for(i=0;i<10*time;i++)delay(10000); //延时4秒关锁relay=0;LcdWriteCom(0x01);LcdWriteCom(0x80);for(i=0;i<14;i++)LcdWriteData(title[i]);LcdWriteCom(0x80+0x40);LcdWriteCom(0x0f);num3=3; //开锁后重置开锁的次数return; //开锁就跳出该函数} } }else //如果寄存数组的密码位数与设定的密码位数不相同则不开锁relay=0;LcdWriteCom(0x80);for(i=0;i<16;i++)LcdWriteData(tishi1[i]);LcdWriteCom(0x80+0x40);for(i=0;i<9;i++)
LcdWriteData(tishi2[i]);num3--; //开锁失败次数减一LcdWriteData(arr[num3]);LcdWriteCom(0x0c);if(num3==0) //当3次全用完时就陷入死循环并报警{while(1){buzz=1;LcdWriteCom(0x01);LcdWriteCom(0x80);for(i=0;i<11;i++)LcdWriteData(tishi5[i]);for(i=0;i<10;i++)delay(10000);LcdWriteCom(0x01);for(i=0;i<10;i++)delay(10000);if(delet==0)
{delay(10);if(delet==0);while(!delet);}}}for(i=0;i<3*time;i++)delay(10000);LcdWriteCom(0x01);LcdWriteCom(0x80);for(i=0;i<14;i++)LcdWriteData(title[i]);LcdWriteCom(0x80+0x40);LcdWriteCom(0x0f);
}void deletkey() //清屏按键,删除键
{LcdWriteCom(0x01);relay=0;
}void init()
{TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;EX0=1;EX1=1;TR0=1;
}void main(void)
{uchar i=0;LcdInit();init();blak=1;relay=0;buzz=0;LcdWriteCom(0x80);biaoshi:for(i=0;i<14;i++)LcdWriteData(title[i]);LcdWriteCom(0x80+0x40); while(1){ KeyDown(); if(confirm==0){delay(10);if(confirm==0){confirmkey();num1=0;j=0;}while(!confirm);}if(delet==0){delay(10);if(delet==0){deletkey();num1=0;j=0; }while(!delet);goto biaoshi;}if(num>=20) //计时20秒{num=0;num1++;if(num1==sleep) //判断20秒内有无操作{ET0=0;blak=0; LcdWriteCom(0x08);PCON=0x02; //单片机进入休眠}}
}
}void timer0() interrupt 1
{TH0=(65536-50000)/256;TL0=(65536-50000)%256;num++;
}void ex_int1() interrupt 2 //P3^3口唤醒单片机
{PCON=0;ET0=1;num1=0;blak=1;LcdWriteCom(0x0f);
}
看完程序可能会有人问矩阵按键有多余的为什么还要增加几个独立按键,我只想说很方便,哈哈,因为我是在开发板中做的,矩阵按键的按键太多,有时候自己都不知到哪个是那个键了,不方便调试。