找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1813|回复: 3
打印 上一主题 下一主题
收起左侧

基于清翔单片机的简易数码管密码锁程序

[复制链接]
跳转到指定楼层
楼主
ID:966442 发表于 2022-1-28 18:26 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
程序功能: 1、开锁: 下载程序后,直接按六次S6(即代表数字0),8位LED亮,锁被打开,输入密码时,
                  六位数码管依次显示小横杠。
                  2、更改密码:
                  只有当开锁(LED亮)后,该功能方可使用。
                  首先按下更改密码键S16,然后设置相应密码,此时六位数码管会显示设置密码对应
                  的数字。最后设置完六位后,按下S17确认密码更改,此后新密码即生效。
                  3、重试密码:
                  当输入密码时,密码输错后按下键S18,可重新输入六位密码。
                  当设置密码时,设置中途想更改密码,也可按下此键重新设置。
                  4、关闭密码锁:
                  按下S19即可将打开的密码锁关闭。
推荐初级演示步骤:输入原始密码000000按6次S6密码正确后LED全部亮表示锁已打开---按下更
改密码按键S16---按S6到S15设置密码---按S17
                        确认密码更改---按S19关闭密码锁---输入新的密码打开密码锁

        功能键
                                                S6---S15        数字键0-9
                                S16---更改密码                S17---更改密码完毕后确认
                                S18---重试密码、重新设定        S19---关闭密码锁
                                初始密码:000000         密码位数:6位
                                注意:掉电后,所设密码会丢失,重新上点时,密码恢复为原始的000000
                                与P1相连的8位发光LED点亮代表锁被打开;熄灭代表锁被锁上

代码借鉴了例程,例程没什么注释,我基本上很多关键地方都给出了注释,我觉得已经很走心了,代码这种东西要多看多练,稍微几天不打就没啥感觉了,Keil代码下载: 密码锁.rar (40.82 KB, 下载次数: 41)

单片机源程序如下:
  1. #include <REGX52.H>
  2. /******数据变量定义*******/
  3. typedef unsigned char uchar;
  4. typedef unsigned int uint;
  5. /******数据变量定义*******/

  6. /******硬件接口定义*******/
  7. sbit dula = P2^6;
  8. sbit wela = P2^7;
  9. sbit beep = P2^3;
  10. /******硬件接口定义*******/

  11. /******使用到的变量定义*******/
  12. uchar old1,old2,old3,old4,old5,old6;//旧密码,000000
  13. uchar new1,new2,new3,new4,new5,new6;//单片机所接受到的新密码
  14. uchar wei,temp,keyvalue;//wei的增加可以让我们去控制对应的数码管,temp读取P3口的状态,keyvalue为矩阵键盘的键值
  15. uchar a=16;b=16;c=16;d=16;e=16;f=16;//作用于数码管显示函数中的变量,刚开始为不亮
  16. uchar code table[]=
  17. {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
  18.         0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};//共阴数码管,0x00:关闭数码管  0x40:数码管显示'-'这个字样
  19. uchar code we[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf};//数码管对应的位码
  20. bit finish,ok,close,allow,change,reinput;
  21. // change表示s16按键为修改密码键
  22. // finish表示密码全部输完的标志
  23. // ok表示s17确认键按下,密码锁的密码已经更改完毕
  24. // close表示密码锁关闭,灯也会跟着数码管关闭,由s19按键负责
  25. // allow表示只有密码锁密码正确的情况下,才能进行修改密码的操作
  26. // reinput表示密码重新输入,主要用在密码输错或者中途改密码时觉得输错密码的情况下
  27. /******使用到的变量定义*******/

  28. /******延时函数*******/
  29. void delay(unsigned char i)
  30. {
  31.         uchar j,k;
  32.   for(j=i;j>0;j--)
  33.     for(k=125;k>0;k--);
  34. }
  35. /******延时函数*******/

  36. /******看起来方便的函数*******/
  37. /*我看了很多关于74HC573级联驱动数码管的代码
  38. 代码看起来挺长的,我感觉我这种写法会方便一点
  39. 不用写这么多*/
  40. void convenience(uchar duan,uchar wei)
  41. {
  42.         dula = 0;//不懂的可以去看74HC573的芯片手册或者这个芯片驱动数码管的视频看一下
  43.         P0 = table[duan];//传递段码
  44.         dula = 1;
  45.         dula = 0;
  46.         
  47.         wela = 0;
  48.         P0 = we[wei];//传递位码
  49.         wela = 1;
  50.         wela = 0;
  51.         delay(5);
  52. }
  53. /******看起来方便的函数*******/

  54. /******数码管显示函数*******/
  55. //此处abcdef为形参与上面的abcdef不同,上面的abcdef为实参,用来让六位数码管显示想要的符号/数字
  56. void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)
  57. {
  58.         convenience(a,0);
  59.         convenience(b,1);
  60.         convenience(c,2);
  61.         convenience(d,3);
  62.         convenience(e,4);
  63.         convenience(f,5);
  64. }
  65. /******数码管显示函数*******/

  66. /******按键松手检测函数******/
  67. //仿真的我不清楚但是实物的话,松手检测是必须的
  68. //感觉矩阵按键的写法不能跟单个按键一样————可以不加松手检测
  69. //我就曾经因为没加矩阵按键松手检测导致效果有问题
  70. //所以我觉得应该要加
  71. void keyRelease()
  72. {
  73.         while(temp!=0xf0)
  74.         {
  75.                 temp = P3;
  76.                 temp = temp & 0xf0;
  77.                 beep = 0;//按一下蜂鸣器就响
  78.         }
  79.         beep = 1;//蜂鸣器关掉
  80. }
  81. /******按键松手检测函数******/

  82. /******按键扫描函数*******/
  83. void keyscan()
  84. {
  85.         P3 = 0xfe;temp = P3;temp = temp & 0xf0;//检测第一行按键是否有被按下的
  86.         if(temp!=0xf0)//与独立按键写法类似
  87.         {
  88.                 delay(10);//延时
  89.                 if(temp!=0xf0)
  90.                 {
  91.                         temp = P3;//读取P3状态看看是哪个按键被按下
  92.                         switch(temp)
  93.                         {//wei++是干什么用的呢,我会在下面的函数中告诉你
  94.                                 case 0xee:keyvalue=0;wei++;break;//看不懂键值的,先去看看矩阵按键的知识
  95.                                 case 0xde:keyvalue=1;wei++;break;
  96.                                 case 0xbe:keyvalue=2;wei++;break;
  97.                                 case 0x7e:keyvalue=3;wei++;break;
  98.                                 default:break;
  99.                         }
  100.                         keyRelease();//松手检测
  101.                 }
  102.         }
  103.         P3 = 0xfd;temp = P3;temp = temp & 0xf0;//检测第二行按键是否有被按下的
  104.         if(temp!=0xf0)//与独立按键写法类似
  105.         {
  106.                 delay(10);//延时
  107.                 if(temp!=0xf0)
  108.                 {
  109.                         temp = P3;//读取P3状态看看是哪个按键被按下
  110.                         switch(temp)
  111.                         {
  112.                                 case 0xed:keyvalue=4;wei++;break;//看不懂键值的,先去看看矩阵按键的知识
  113.                                 case 0xdd:keyvalue=5;wei++;break;
  114.                                 case 0xbd:keyvalue=6;wei++;break;
  115.                                 case 0x7d:keyvalue=7;wei++;break;
  116.                                 default:break;
  117.                         }
  118.                         keyRelease();//松手检测
  119.                 }
  120.         }
  121.         P3 = 0xfb;temp = P3;temp = temp & 0xf0;//检测第三行按键是否有被按下的
  122.         if(temp!=0xf0)//与独立按键写法类似
  123.         {
  124.                 delay(10);//延时
  125.                 if(temp!=0xf0)
  126.                 {
  127.                         temp = P3;//读取P3状态看看是哪个按键被按下
  128.                         switch(temp)
  129.                         {
  130.                                 case 0xeb:keyvalue=8;wei++;break;//看不懂键值的,先去看看矩阵按键的知识
  131.                                 case 0xdb:keyvalue=9;wei++;break;
  132.                                 case 0xbb:change=1;wei=0;break;//s16按键,修改密码
  133.                                 case 0x7b:
  134.                                         if(allow)//只有密码正确,allow才会为1
  135.                                         {
  136.                                                 ok = 1;//确认密码修改完毕
  137.                                         }
  138.                                         break;//s17按键 密码修改完毕确认键
  139.                                 default:break;
  140.                         }
  141.                         keyRelease();//松手检测
  142.                 }
  143.         }
  144.         P3 = 0xf7;temp = P3;temp = temp & 0xf0;//检测第四行按键是否有被按下的
  145.         if(temp!=0xf0)//与独立按键写法类似
  146.         {
  147.                 delay(10);//延时
  148.                 if(temp!=0xf0)
  149.                 {
  150.                         temp = P3;//读取P3状态看看是哪个按键被按下
  151.                         switch(temp)
  152.                         {
  153.                                 case 0xe7:reinput=1;break;//s18 重新修改或输入密码
  154.                                 case 0xd7:close=1;break;//s19 关闭密码锁和灯
  155.                                 default:break;
  156.                         }
  157.                         keyRelease();//松手检测
  158.                 }
  159.         }
  160. }
  161. /******按键扫描函数*******/

  162. /******输入密码函数*******/
  163. void InputPassword()
  164. {
  165.         if(!finish)//finish为1表示密码全部输入完毕,为0表示密码没输完
  166.         {
  167.                 //wei=0,就是不操控数码管 wei=1就是操控第一个数码管,wei=2就是操控第二个数码管,依此类推,这就是wei的作用
  168.                 switch(wei)
  169.                 {
  170.                         case 1:new1=keyvalue;//第一个数码管接收矩阵按键的密码信息
  171.                                 if(!allow)//在密码没输入正确前,每按一次按键数码管依次显示'-',相当于隐藏密码吧
  172.                                         a=17;//如果密码错误,则数码管显示'-'字符
  173.                                 else//allow为1,一般就是说可以改密码了,这个时候每按一次按键,数码管依次显示对应的数字
  174.                                         a=keyvalue;//将键值赋给a,a再传递到数码管显示函数
  175.                                 break;
  176.                         case 2:new2=keyvalue;//照猫画虎更上面类似
  177.                                 if(a==17)
  178.                                         b=17;//如果第一个数码管显示'-'那么接下来的数码管也要显示'-'
  179.                                 else
  180.                                         b=keyvalue;
  181.                                 break;
  182.                         case 3:new3=keyvalue;
  183.                                 if(a==17)
  184.                                         c=17;//如果第一个数码管显示'-'那么接下来的数码管也要显示'-'
  185.                                 else
  186.                                         c=keyvalue;
  187.                                 break;
  188.                         case 4:new4=keyvalue;
  189.                                 if(a==17)
  190.                                         d=17;//如果第一个数码管显示'-'那么接下来的数码管也要显示'-'
  191.                                 else
  192.                                         d=keyvalue;
  193.                                 break;
  194.                         case 5:new5=keyvalue;
  195.                                 if(a==17)
  196.                                         e=17;//如果第一个数码管显示'-'那么接下来的数码管也要显示'-'
  197.                                 else
  198.                                         e=keyvalue;
  199.                                 break;
  200.                         case 6:new6=keyvalue;
  201.                                 if(a==17)
  202.                                         f=17;//如果第一个数码管显示'-'那么接下来的数码管也要显示'-'
  203.                                 else
  204.                                         f=keyvalue;
  205.                                         finish = 1;//就此,六位数码管密码全部输完
  206.                                 break;
  207.                 }
  208.         }
  209. }
  210. /******输入密码函数*******/

  211. /******验证密码正确函数*******/
  212. void CheckPassword()
  213. {
  214.         if(finish)
  215.         {
  216.                 //新旧密码对比,正确就allow=1
  217.                 if((new1==old1)&(new2==old2)&(new3==old3)&(new4==old4)&(new5==old5)&(new6==old6))
  218.                 {
  219.                         allow = 1;//只有原始密码正确才可以进行下面的修改密码的操作
  220.                 }
  221.         }
  222. }
  223. /******验证密码正确函数*******/

  224. /******主函数******/
  225. void main()
  226. {
  227.         while(1)
  228.         {
  229.                 keyscan();//按键扫描
  230.                 InputPassword();//输入密码
  231.                 CheckPassword();//确认密码
  232.                 if(allow)
  233.                 {
  234.                         P1=0x00;//灯全亮
  235.                         if(!change)//没有进行修改密码操作时,应把finish置零
  236.                                 finish = 0;
  237.                 }
  238.                 if(change)//进行修改密码操作时
  239.                 {
  240.                         if(allow)//原始密码正确才能进行操作
  241.                         {
  242.                                 while(!finish)//只有密码全部输完才能退出循环
  243.                                 {
  244.                                         keyscan();//因为卡在这里的while循环,不能再返回到上面的扫描语句,故要加上去
  245.                                         InputPassword();//与上同理
  246.                                         if(reinput|close)//如果重新修改密码或者关闭密码锁
  247.                                         {
  248.                                                 finish = 1;//退出循环
  249.                                                 break;
  250.                                         }
  251.                                         display(a,b,c,d,e,f);//显示修改密码的数字
  252.                                 }
  253.                         }
  254.                 }
  255.                 if(ok)//密码修改完毕
  256.                 {
  257.                         ok = 0;//不用多说
  258.                         wei = 0;//从头开始输密码啦
  259.                         change = 0;//不用再改啦
  260.                         old1=new1;old2=new2;old3=new3; //此时,旧的密码将被代替
  261.                         old4=new4;old5=new5;old6=new6;
  262.                         a=b=c=e=f=d=16;//数码管不亮,你可以理解为视觉效果更好看一点把
  263.                 }
  264.                 if(reinput)//重新输入密码
  265.                 {
  266.                         reinput = 0;//这个肯定要等于0吧,不然就一直逃不出这个if了
  267.                         wei = 0;//这个肯定也要0吧,不然一直wei++就超过了数码管的位数啦
  268.                         finish = 0;//你重新输入密码,是不是密码没输完,那么这个肯定也要0吧
  269.                         new1=new2=new3=new4=new5=new6=0;//把我们之前输错的密码全清零了
  270.                         a=b=c=e=f=d=16;//你重新输入密码,数码管不亮
  271.                 }
  272.                 if(close)//关闭密码锁
  273.                 {
  274.                         close = 0;//关闭数码管,万物皆0
  275.                         allow = 0;
  276.                         wei = 0;
  277.                         finish = 0;
  278.                         change = 0;
  279.                         P1 = 0xff;//灯要关啦
  280.                         new1=new2=new3=new4=new5=new6=0;//把我们之前输错的密码全清零了
  281.                         a=b=c=e=f=d=16;//你重新输入密码,数码管不亮
  282.                 }
  283.                 display(a,b,c,d,e,f);//不属于任何一个if,实时显示
  284.         }
  285. }
  286. /******主函数******/
复制代码
原本想发一个演示的视频但是容量有点大,就不发了


评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:399179 发表于 2022-3-26 22:00 来自手机 | 只看该作者
这个程序断电后不能记忆新密码吧?
回复

使用道具 举报

板凳
ID:718536 发表于 2022-3-31 22:20 | 只看该作者
快乐眼泪 发表于 2022-3-26 22:00
这个程序断电后不能记忆新密码吧?

加上EEPROM程序就可以断电记忆了。在主程序那里读取一下设置的密码。
回复

使用道具 举报

地板
ID:332444 发表于 2023-2-24 13:50 | 只看该作者
刚刚出炉的普中板子密码锁8位不用数组,三次错误显示ERROR演示。
数码管驱动138-573,错误有蜂鸣,正确LED显示,单按键确认密码。

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表