看到电影里面的保险箱用到的密码锁,于是心血来潮动手做了一个简单的密码锁,其有3次输入的机会,全错的话便进入死循环,一直警报,任何操作都无效,除了复位操作哈。所需素材:51单片机、1602液晶、蜂鸣器、按键、继电器、三极管、电磁锁等。话不多说,直接上代码:
#include
#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); //写一个指针加1
LcdWriteCom(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; //将按下的数值赋给check
j++;
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 { if(possword[i]==check[i]) //判断寄存数组的密码与设定的密码是否相等 { k++; } else { break; } if(k==size) // 如果寄存数组中每个数都与设定的密码相等,就开锁 { relay=1; for(i=0;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); } 看完程序可能会有人问矩阵按键有多余的为什么还要增加几个独立按键,我只想说很方便,哈哈,因为我是在开发板中做的,矩阵按键的按键太多,有时候自己都不知到哪个是那个键了,不方便调试。