物料清单: 52单片机最小系统板×1
3×4矩阵键盘
4位共阴数码管×2
74hc245
24c02
电磁锁头
功能:
1、具有默认状态数码管不显示,输入一位上一位清零的掩码功能
2、按下确认键对比密码
3,输入更改密码的密码后,可开始设置新密码1-8位密码
4,掉电不重置密码,带重置按键。
代码思路:
(代码是小编我自己独立设计的有些地方不太行,可自行更改)
(数码管显示函数,矩阵按键键值传递函数……直接复制粘贴吧,有时间会出教程)
密码对比、存储函数,密码更改,掩码……如何实现?
本来打算画图的,觉得画的太差就打个比方(有的不太恰当,见谅!)
快递员,张三,李四家。
跑腿每接一单就有一个快递要送到张三家0 --- 张三家7
如何保证不送错呢?
是不是每个快递上都要写一个数…… 张三家0, 张三家1, 张三家2,…… 张三家7
这样快递员是不是就知道放哪了?李四家是不是也可以这样?
但是! 张三家与李四家住一个村,跑腿又不知道那个是张三家,怎么办?
在快递上再加一个标志:门牌上写着0就是张三家,门牌上写着1就是李四家……
这样跑腿拿到快递是不是就知道送到哪?
密码存储代码如下:
void enter_password(unsigned char pwrd_key)//将输入密码存储在相应位置
{
if(pwrd_key)//约束键值,零不置入,
{
//因为需要一个约束条件来达到键值按下标志位加一
//所以将0设置成约束条件了,故键值也就不能出现零
//所以需要伪装一下,给一个特殊的定义,
//当骗过判断便置回零
if(pwrd_key==14){pwrd_key=0;}
if(pattern==0)//判断是正常工作还是密码设置工作模式
{
digit++;//密码输入位数标志位
switch(digit) //switch语句依照位数标志位进行对比此次数据,并放到相应位置
{
case 1:yanma[0]=temp[0]=pwrd_key;break;
case 2:yanma[1]=temp[1]=pwrd_key;break;
case 3:yanma[2]=temp[2]=pwrd_key;break;
case 4:yanma[3]=temp[3]=pwrd_key;break;
case 5:yanma[4]=temp[4]=pwrd_key;break;
case 6:yanma[5]=temp[5]=pwrd_key;break;
case 7:yanma[6]=temp[6]=pwrd_key;break;
case 8:yanma[7]=temp[7]=pwrd_key;break;
}
}
if(pattern==1)//判断是正常工作还是密码设置工作模式
{
mimadigit++;//上同,密码输入位数标志位
switch(mimadigit) //上同
{
case 1:set_password[0]=pwrd_key;break;
case 2:set_password[1]=pwrd_key;break;
case 3:set_password[2]=pwrd_key;break;
case 4:set_password[3]=pwrd_key;break;
case 5:set_password[4]=pwrd_key;break;
case 6:set_password[5]=pwrd_key;break;
case 7:set_password[6]=pwrd_key;break;
case 8:set_password[7]=pwrd_key;break;
}
}
if(digit==8)
{
duibimima();//当密码达到最大位数自动进行密码校对
}
}
}
但张三买了快递他妈妈觉得不好,很多东西没有必要买,并且他妈妈只允许买1-8个快递……
那是不是张三只能买他妈妈觉得可以的快递,并且只能买4个?
所以张三妈妈在张三1-8个房间一个一个看到没必要买的东西便丢出去了,如果买多了直接全部丢掉,如果都是有用的就留下。
但是呢,李四妈妈对李四更严格只能买4个快递,还必须得是她规定的东西,他妈妈才不会丢掉。如果张三买的快递是4个快递并且快递是他妈妈规定的东西,他妈妈是不是就会很开心?
但张三妈和李四妈8个房间都看一下是不是很浪费时间?怎么办呢?
跑腿每次来都会包一个快递吧?那直接看着跑腿来几次不就可以了,
密码校对不就可以实现了?
密码校对,密码更改模式与正常模式切换代码如下
void duibimima()//密码校对(涵改密码功能,并且掉电不掉改动的密码)
{
/*判断上一次密码校对是否是设置密码校对,
如果是则覆盖原密码一次,然后置零,改成正常工作模式*/
if(pattern==1)
{
if(mimadigit==0)
{
r_dushuju();
}
else
{
w_shuju();
}
pattern=0;
}
/*密码校对:先进行位数判断如果位数等于4的话便进行一次权限密码校对。
如何再将标志位与设置密码位数的标志位对比,如果相等则开始密码校对
密码校对采用for循环校对,
*/
mimaok=0;
if(digit==4)
{
for(i=0;i<4;i++)
{
if(mima_ON[i]==temp[i])//权限密码校对
{
mimaok++; //权限标志位
if(mimaok==4)
{
mimaok=0;
pattern=1; //工作模式切换
mimadigit=0; //密码设置标志位数清零,准备存储新密码
mima_szqing0(); //清除设置密码
}
}
}
}
if(mimadigit!=digit){qing0();}//先进行位数对比,如果位数不相等直接清零
for(i=0;i<mimadigit;i++)//先将暂存数组的数据与设置好的密码对比
{
if(set_password[i]==temp[i])//两个数组相应位号对比,如何相同
{ //就把成功校对标志位加一次
mimaok++; //暂存密码标志位
if(mimaok==mimadigit) //对比一下设置密码的位数等于成功校对标志
{ //则表示密码正确,反之则错误,
mimaok=0;
P2_7=0;
delay(300);
P2_7=1;
}
}
}
digit=0;//正常工作密码标志位清零,
qing0();//清屏,为下一次做准备
}
那怎么实现改密码呢?
上面存储密码是不是发现有个模式判断?
对!就看李四妈妈心情好不好,好的话就说明要改密码吧?
这样话就只需要判断李四密码心情好不好了,好的话就把密码给密码数组,覆盖原密码,不好就把密码就放到暂存数组。
那怎么做到掉电不重置密码呢?
24c02!模块直接复制粘贴用,小编也忘记当时咋写的了。(不会告诉你小编之所以写这个教程是因为小编十分健忘……)
在密码设置完成后调用一个写数组将新密码存进去,然后在mian函数第一行就调用读,也就是上电就读一下写进去的密码,并存到密码数组中。
主函数调用如下
void main()
{
Timer0Init();//定时器初始化
r_dushuju();//读取24c02数据
while(1)
{
keynum=MatrixKey();//接收键值
if(keynum!=13 && keynum!=15 && keynum!=0 && keynum!=10)//过滤功能按键
{enter_password(keynum);}
if(keynum==13){duibimima();}//密码校对
if(keynum==15)//清空显示数据
{
if(pattern==0)
{
qing0();
}
if(pattern==1)
{
mima_szqing0();
}
}
if(keynum==10){w_init();r_dushuju();keynum=0;}//重置
}
}
那如何实现按键按后,上一位显示数据熄灭呢?
再加一个数组,有按键按下不是在密码更改工作模式下就把这个键值同时给暂存数组与显示数组
检查显示数组上一位是否为零,并且!!! 下一位是否不为零(不加后面这个条件会出现一个bug,哪位大佬可以试试破解一下)如果符合就把上一位清零不就完美了?
显示掩码代码如下:
if(pattern==0)
{
for(x=0;x<8;x++)
{
shumaguan(x+1,yanma[x]);
if(x>0)
{
if(yanma[x]!=10 && yanma[x-1]!=10){yanma[x-1]=10;}
}
}
}
这样:密码校对,存储,更改,掩码显示不就完美解决了?
总结:巧用标志位与数组的特性。
硬件方面就不多介绍了,小编不太在行
仿真图如下:
PCB图如下:
正面
反面
完整项目文件:
链接:链接:https://pan.baidu.com/s/1Hvv5DJDubhrkSC3DnkwXdQ?pwd=at51
提取码:at51
小编承接双层板PCB设计,52单片机芯片的设计开发,PCB代焊代测试
价格优惠,有需要的各位老板可找我私聊。