找回密码
 立即注册

QQ登录

只需一步,快速开始

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

51单片机密码锁资料 可以掉电储存数据

[复制链接]
跳转到指定楼层
楼主
ID:239210 发表于 2017-10-13 17:54 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
网上找的清翔密码锁代码
希望可以帮到大家


  1. /*********************************************************************************
  2. * 【编写时间】: 2014年3月5日
  3. * 【作    者】: 清翔电子:03
  4. * 【版    本】: 1.0
  5. * 【实验平台】: QX-MCS51 单片机开发板
  6. * 【外部晶振】: 11.0592mhz
  7. * 【主控芯片】: STC89C52
  8. * 【编译环境】: Keil μVisio3
  9. * 【程序功能】: 此程序应用AT24C02芯片可以掉电储存数据                           
  10. * 【使用说明】:
  11. *  说明:免费开源,不提供源代码分析.
  12. **********************************************************************************/
  13. /********************************************************************************
  14.         功能键
  15.       S6---S115 数字键0-9
  16.     S16---更改密码  S17---更改密码完毕后确认
  17.     S18---重试密码、重新设定 S19---关闭密码锁
  18.     初始密码:000000  密码位数:6位
  19.     注意:掉电后,所设密码会丢失,重新上点时,密码恢复为原始的000000
  20.     与P1相连的8位发光LED点亮代表锁被打开;熄灭代表锁被锁上
  21. 程序功能:
  22.     1、开锁:
  23.     下载程序后,直接按六次S6(即代表数字0),8位LED亮,锁被打开,输入密码时,
  24.     六位数码管依次显示小横杠。
  25.     2、更改密码:
  26.     只有当开锁(LED亮)后,该功能方可使用。
  27.     首先按下更改密码键S16,然后设置相应密码,此时六位数码管会显示设置密码对应
  28.     的数字。最后设置完六位后,按下S17确认密码更改,此后新密码即生效。
  29.     3、重试密码:
  30.     当输入密码时,密码输错后按下键S18,可重新输入六位密码。
  31.     当设置密码时,设置中途想更改密码,也可按下此键重新设置。
  32.     4、关闭密码锁:
  33.     按下S19即可将打开的密码锁关闭。
  34. 推荐初级演示步骤:输入原始密码000000按6次S6密码正确后LED全部亮表示锁已打开---按下更
  35. 改密码按键S16---按S6到S15设置密码---按S17
  36.    确认密码更改---按S19关闭密码锁---输入新的密码打开密码锁
  37. *******************************************************************************/
  38. #include<reg52.h>
  39. #include <intrins.h>
  40. #define uint unsigned int
  41. #define uchar unsigned char
  42. uchar old1,old2,old3,old4,old5,old6; //原始密码000000
  43. uchar new1,new2,new3,new4,new5,new6;  //每次MCU采集到的密码输入
  44. uchar a=16,b=16,c=16,d=16,e=16,f=16; //送入数码管显示的变量
  45. uchar wei,key,temp;
  46. bit allow,genggai,ok,wanbi,retry,close;  //各个状态位
  47. sbit dula=P2^6;
  48. sbit wela=P2^7;
  49. sbit beep=P2^3;
  50. sbit sda=P2^0;                          //IO口定义
  51. sbit scl=P2^1;
  52. unsigned char code table[]=
  53. {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
  54. 0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};
  55. /*****************IIC芯片24C02存储器驱动程序************************************/
  56. void nop()
  57. {
  58. _nop_();
  59. _nop_();
  60. }
  61. /////////24C02读写驱动程序////////////////////
  62. void delay1(unsigned int m)
  63. { unsigned int n;
  64.    for(n=0;n<m;n++);
  65. }
  66. void init()  //24c02初始化子程序
  67. {
  68. scl=1;
  69. nop();
  70. sda=1;
  71. nop();
  72. }
  73. void start()        //启动I2C总线
  74. {
  75. sda=1;
  76. nop();
  77. scl=1;
  78. nop();
  79. sda=0;
  80. nop();
  81. scl=0;
  82. nop();
  83. }
  84. void stop()         //停止I2C总线
  85. {
  86. sda=0;
  87. nop();
  88. scl=1;
  89. nop();
  90. sda=1;
  91. nop();
  92. }
  93. void writebyte(unsigned char j)  //写一个字节
  94. {
  95. unsigned char i,temp;
  96.     temp=j;
  97.     for (i=0;i<8;i++)
  98.    {
  99.     temp=temp<<1;
  100.     scl=0;
  101.     nop();
  102.     sda=CY;  //temp左移时,移出的值放入了CY中
  103.     nop();
  104.     scl=1;  //待sda线上的数据稳定后,将scl拉高
  105.     nop();
  106.    }
  107.    scl=0;
  108.    nop();
  109.    sda=1;
  110.    nop();
  111. }
  112. unsigned char readbyte()   //读一个字节
  113. {
  114.    unsigned char i,j,k=0;
  115.    scl=0; nop(); sda=1;
  116.    for (i=0;i<8;i++)
  117.    {  
  118.   nop(); scl=1; nop();
  119.        if(sda==1)
  120.   j=1;
  121.        else
  122.   j=0;
  123.        k=(k<<1)|j;
  124.     scl=0;
  125. }
  126.     nop();
  127. return(k);
  128. }
  129. void clock()         //I2C总线时钟
  130. {
  131.    unsigned char i=0;
  132.    scl=1;
  133.    nop();
  134.    while((sda==1)&&(i<255))
  135.       i++;
  136.    scl=0;
  137.    nop();
  138. }
  139. ////////从24c02的地址address中读取一个字节数据/////
  140. unsigned char read24c02(unsigned char address)
  141. {
  142.    unsigned char i;
  143.    start();
  144.    writebyte(0xa0);
  145.    clock();
  146.    writebyte(address);
  147.    clock();
  148.    start();
  149.    writebyte(0xa1);
  150.    clock();
  151.    i=readbyte();
  152.    stop();
  153.    delay1(100);
  154.    return(i);
  155. }
  156. //////向24c02的address地址中写入一字节数据info/////
  157. void write24c02(unsigned char address,unsigned char info)
  158. {
  159.    start();
  160.    writebyte(0xa0);
  161.    clock();
  162.    writebyte(address);
  163.    clock();
  164.    writebyte(info);
  165.    clock();
  166.    stop();
  167.    delay1(5000); //这个延时一定要足够长,否则会出错。因为24c02在从sda上取得数据后,还需要一定时间的烧录过程。
  168. }
  169. /****************************密码锁程序模块********************************************************/
  170. void delay(unsigned char i)
  171. {
  172. uchar j,k;
  173.   for(j=i;j>0;j--)
  174.     for(k=125;k>0;k--);
  175. }
  176. void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)
  177. {
  178.    dula=0;
  179.    P0=table[a];
  180.    dula=1;
  181.    dula=0;
  182.    
  183.    wela=0;
  184.    P0=0xfe;
  185.    wela=1;
  186.    wela=0;
  187.    delay(5);
  188.    
  189.    P0=table[b];
  190.    dula=1;
  191.    dula=0;
  192.    
  193.    P0=0xfd;
  194.    wela=1;
  195.    wela=0;
  196.    delay(5);
  197.    P0=table[c];
  198.    dula=1;
  199.    dula=0;
  200.    
  201.    P0=0xfb;
  202.    wela=1;
  203.    wela=0;
  204.    delay(5);
  205.    
  206.    P0=table[d];
  207.    dula=1;
  208.    dula=0;
  209.    
  210.    P0=0xf7;
  211.    wela=1;
  212.    wela=0;
  213.    delay(5);
  214.    
  215.    P0=table[e];
  216.    dula=1;
  217.    dula=0;
  218.    
  219.    P0=0xef;
  220.    wela=1;
  221.    wela=0;
  222.    delay(5);
  223.    
  224.    P0=table[f];
  225.    dula=1;
  226.    dula=0;
  227.    
  228.    P0=0xdf;
  229.    wela=1;
  230.    wela=0;
  231.    delay(5);
  232. }

  233. void keyscan()
  234. {
  235.   {
  236.     P3=0xfe;
  237.     temp=P3;
  238.     temp=temp&0xf0;
  239.     if(temp!=0xf0)
  240.     {
  241.       delay(10);
  242.       if(temp!=0xf0)
  243.       {
  244.         temp=P3;
  245.         switch(temp)
  246.         {
  247.           case 0xee:
  248.                key=0;
  249.       wei++;
  250.                break;
  251.           case 0xde:
  252.                key=1;
  253.       wei++;
  254.                break;
  255.           case 0xbe:
  256.                key=2;
  257.       wei++;
  258.                break;
  259.           case 0x7e:
  260.                key=3;
  261.       wei++;
  262.                break;
  263.          }
  264.          while(temp!=0xf0)
  265.         {
  266.            temp=P3;
  267.            temp=temp&0xf0;
  268.            beep=0;
  269.          }
  270.          beep=1;
  271.       }
  272.     }
  273.     P3=0xfd;
  274.     temp=P3;
  275.     temp=temp&0xf0;
  276.     if(temp!=0xf0)
  277.     {
  278.       delay(10);
  279.       if(temp!=0xf0)
  280.       {
  281.         temp=P3;
  282.         switch(temp)
  283.         {
  284.           case 0xed:
  285.                key=4;
  286.       wei++;
  287.                break;
  288.           case 0xdd:
  289.                key=5;
  290.       wei++;
  291.                break;
  292.           case 0xbd:
  293.                key=6;
  294.       wei++;
  295.                break;
  296.           case 0x7d:
  297.                key=7;
  298.       wei++;
  299.                break;
  300.          }
  301.          while(temp!=0xf0)
  302.          {
  303.            temp=P3;
  304.            temp=temp&0xf0;
  305.            beep=0;
  306.          }
  307.          beep=1;
  308.       }
  309.       }
  310.     P3=0xfb;
  311.     temp=P3;
  312.     temp=temp&0xf0;
  313.     if(temp!=0xf0)
  314.     {
  315.       delay(10);
  316.       if(temp!=0xf0)
  317.       {
  318.         temp=P3;
  319.         switch(temp)
  320.         {
  321.           case 0xeb:
  322.                key=8;
  323.       wei++;
  324.                break;
  325.           case 0xdb:
  326.                key=9;
  327.       wei++;
  328.                break;
  329.       
  330.           case 0xbb:
  331.                genggai=1;
  332.       wei=0;
  333.                break;
  334.           case 0x7b:
  335.         if(allow)
  336.                ok=1;
  337.                break;
  338.          }
  339.         while(temp!=0xf0)
  340.          {
  341.            temp=P3;
  342.            temp=temp&0xf0;
  343.            beep=0;
  344.          }
  345.          beep=1;
  346.       }
  347.       }
  348.    P3=0xf7;
  349.     temp=P3;
  350.     temp=temp&0xf0;
  351.     if(temp!=0xf0)
  352.     {
  353.       delay(10);
  354.       if(temp!=0xf0)
  355.       {
  356.         temp=P3;
  357.         switch(temp)
  358.         {
  359.           case 0xe7:
  360.         retry=1;
  361.                break;
  362.           case 0xd7:
  363.         close=1;
  364.                break;
  365.          }
  366.         while(temp!=0xf0)
  367.          {
  368.            temp=P3;
  369.            temp=temp&0xf0;
  370.            beep=0;
  371.          }
  372.          beep=1;
  373.       }
  374.       }
  375. }
  376. }
  377. void shumima()  //对按键采集来的数据进行分配
  378. {
  379. if(!wanbi)
  380. {
  381. switch(wei)
  382. {
  383.   case 1:new1=key;
  384.        if(!allow) a=17;
  385.       else a=key; break;
  386.   case 2:new2=key;
  387.     if(a==17) b=17;
  388.     else b=key; break;
  389.   case 3:new3=key;
  390.     if(a==17) c=17;
  391.     else c=key; break;
  392.   case 4:new4=key;
  393.     if(a==17) d=17;
  394.     else d=key; break;
  395.   case 5:new5=key;
  396.     if(a==17) e=17;
  397.     else e=key; break;
  398.   case 6:new6=key;
  399.     if(a==17) f=17;
  400.     else f=key;
  401.     wanbi=1; break;
  402. }
  403. }
  404. }
  405. void yanzheng()   //验证密码是否正确
  406. {
  407. if(wanbi)  //只有当六位密码均输入完毕后方进行验证
  408. {
  409. if((new1==old1)&(new2==old2)&(new3==old3)&(new4==old4)&(new5==old5)&(new6==old6))
  410.   allow=1; //当输入的密码正确,会得到allowe置一
  411. }
  412. }
  413. void main()
  414. {

  415. init();        //初始化24C02
  416. /*********下面的一小段程序的功能为格式化密码存储区。************
  417. ******当24c02中这些存储区由于其他程序的运行而导致***************
  418. *******所存数据发生了变化,或者密码遗忘时, ********************
  419. ******可以删掉其前面的注释线,然后重新编译下载。****************
  420. ******而将密码还原为000000后,请将下面的程序用******************
  421. ******注释屏蔽掉,重新编译、下载,方可正常使用****************/
  422. // write24c02(110,0x00);
  423. // write24c02(111,0x00);//24c02的第110到115地址单元作为密码存储区
  424. // write24c02(112,0x00);
  425. // write24c02(113,0x00);
  426. // write24c02(114,0x00);
  427. // write24c02(115,0x00);
  428. /*******************************************************************/

  429. old1=read24c02(110);  
  430. old2=read24c02(111);
  431. old3=read24c02(112);
  432. old4=read24c02(113);
  433. old5=read24c02(114);
  434. old6=read24c02(115);
  435. while(1)
  436. {
  437.   keyscan();
  438.   shumima();
  439.   yanzheng();
  440.   if(allow)  //验证完后,若allow为1,则开锁
  441.   {
  442.    P1=0x00;
  443.    if(!genggai)
  444.     wanbi=0;
  445.   }
  446.   if(genggai)   //当S16更改密码键被按下,genggai会被置一
  447.   {
  448.    if(allow)  //若已经把锁打开,才有更改密码的权限
  449.    {
  450.     while(!wanbi) //当新的六位密码没有设定完,则一直在这里循环
  451.     {
  452.       keyscan();
  453.      shumima();
  454.      if(retry|close)  //而当探测到重试键S18或者关闭密码锁键S19被按下时,则跳出
  455.      { wanbi=1;
  456.       break;
  457.      }
  458.      display(a,b,c,d,e,f);
  459.     }
  460.    }
  461.   }
  462.   if(ok)   //更改密码时,当所有六位新密码均被按下时,可以按下此键,结束密码更改
  463.   {    //其他时间按下此键无效
  464.    ok=0; wei=0;
  465.    genggai=0;
  466.    old1=new1;old2=new2;old3=new3; //此时,旧的密码将被代替
  467.    old4=new4;old5=new5;old6=new6;
  468.    //新密码写入存储区。
  469.    write24c02(110,old1);
  470.    write24c02(111,old2);
  471.    write24c02(112,old3);
  472.    write24c02(113,old4);
  473.    write24c02(114,old5);
  474.    write24c02(115,old6);
  475.    a=16;b=16;c=16;d=16;e=16;f=16;
  476.   }
  477.   if(retry) //当重试按键S18被按下,retry会被置位
  478.   {
  479.   retry=0; wei=0;wanbi=0;
  480.   a=16;b=16;c=16;d=16;e=16;f=16;
  481.   new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;  
  482.   }
  483.   if(close)  //当关闭密码锁按键被按下,close会被置位
  484.   {
  485.    close=0;genggai=0;//所有变量均被清零。
  486.    wei=0; wanbi=0;
  487.    allow=0;
  488.    P1=0xff;
  489.    a=16;b=16;c=16;d=16;e=16;f=16;
  490.    new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;
  491.   }
  492.   display(a,b,c,d,e,f); //实时显示
  493. }
  494. }
复制代码

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

使用道具 举报

沙发
ID:358326 发表于 2018-6-25 12:40 | 只看该作者
大哥  有图吗?
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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