找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15175|回复: 25
收起左侧

DIY制作单片机断电密码保存电子锁,含原理图

  [复制链接]
ID:70481 发表于 2014-12-17 00:09 | 显示全部楼层 |阅读模式
DIY单片机断电密码保存电子锁电子密码锁是集计算机技术、电子技术、数字密码技术为一体的机电一体化高科技产品,具有安全性高,使用方便等优点。本论文从电子密码锁系统的功能,硬件电路设计,软件设计分别论述这一系统。通过使用单片机AT89S52作为控制核心,连接外部存储器AT24C02,实现密码断电保存,制作一种密码锁。
102217mi5q6io5i4jd6eho.jpg.thumb.jpg 102218zcm2wi520own7884.jpg.thumb.jpg
单片机断电密码保存电子锁.rar (84.01 KB, 下载次数: 175)

评分

参与人数 2黑币 +17 收起 理由
tianxiadiyi + 5 赞一个!
zhaok2013 + 12 很给力!

查看全部评分

回复

使用道具 举报

ID:70481 发表于 2014-12-17 00:10 | 显示全部楼层
下面是源码预览
  1. 数码管的A--H 引脚 接到单片机的p0 口的 p0^0--P0^7 引脚  .

  2. 电路图也有点问题,AT24C02 的引脚应该是 sbit Scl=P3^4; //串行时钟信号
  3.                                            sbit Sda=P3^5; //串行数据信号




  4. #define uchar unsigned char //定义一下方便使用
  5. #include "reg52.h"
  6. #include "intrins.h"         //调用头文件
  7. #define WriteDeviceAddress  0xa0   // AT24C02的识别码是1010,硬件的三个地址引脚接地为000,最后一位为0时表示向存储器写入数据
  8. #define ReadDviceAddress  0xa1     //最后一位为1时表示从存储器读出数据。0xa0=1010 000 0 ,0xa1=1010 000 1 .
  9. sbit Scl=P3^4; //串行时钟信号
  10. sbit Sda=P3^5; //串行数据信号
  11. sbit  xin=P2^0;   //在硬件电路上驱动青色发光二极管,用与显示当前处于密码输入状态
  12. sbit    xin_on=P3^6; //  在硬件电路上驱动继电器,当8位密码输入正确时,继电器工作
  13. sbit    ch_pass=P2^2;   //  在硬件电路上驱动红色发光二极管,用于显示当前处于修改密码状态
  14. sbit    on=P3^7;
  15. static  cound ;    //  用于计算密码输入的个数,每次输入8位密码后,清0

  16. uchar  code DB_dat[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};     // 存放数码管显示字符码
  17. uchar  DB_password[8];    //    存放从存储器中读取的原始密码
  18. uchar  DB_inword[8];   //    存放从键盘输入的密码
  19.                                           
  20. void DelayMs(unsigned int number)       //延时函数 延时1 MS
  21. {
  22. unsigned char temp;
  23. for(;number!=0;number--)
  24. {
  25.   for(temp=112;temp!=0;temp--) ;
  26. }
  27. }


  28. void Start(void)       /
  29. {
  30.         Sda=0;
  31.         Scl=1;
  32.         _nop_ ();      //根据时序图尽心延时
  33.         _nop_ ();
  34.         _nop_ ();
  35.         _nop_ ();
  36.         Sda=1;
  37.         _nop_ ();
  38.         _nop_ ();
  39.         _nop_ ();
  40.         _nop_ ();
  41. }
  42. void Ack(void)
  43. {
  44.         Sda=0;
  45.          _nop_ ();
  46.         _nop_ ();    //延时 根据时序图
  47.         _nop_ ();
  48.         _nop_ ();
  49.         Scl=1;
  50.         _nop_ ();
  51.         _nop_ ();
  52.         _nop_ ();
  53.         _nop_ ();
  54.         Scl=0;
  55. }
  56. void  NoAck(void)      
  57. {
  58.         Sda=1;
  59.         _nop_ ();    //根据时序图进行延时
  60.         _nop_ ();
  61.         _nop_ ();
  62.         _nop_ ();
  63.         Scl=1;
  64.         _nop_ ();
  65.         _nop_ ();
  66.         _nop_ ();
  67.         _nop_ ();
  68.         Scl=0;
  69. }
  70. void Send(uchar Data)  
  71. {        
  72.         uchar BitCounter=8;      
  73.         uchar temp;   
  74.         do
  75.         {
  76.            temp=Data;
  77.            Scl=0;
  78.            _nop_ ();
  79.            _nop_ ();
  80.            _nop_ ();
  81.            _nop_ ();
  82.            if((temp&0x80)==0x80)
  83.                 Sda=1;
  84.            else
  85.                 Sda=0;        //如果最高位是0就发送0
  86.            Scl=1;
  87.            temp=Data<<1;      
  88.            Data=temp;      
  89.            BitCounter--;       //没发完一位数据就减一
  90.          }while(BitCounter);    //如果发送完8位后跳出循环
  91.          Scl=0;               //释放总线           
  92. }
  93. uchar Read(void)
  94. {
  95.         uchar temp=0;
  96.         uchar temp1=0;
  97.         uchar BitCounter=8;   //定义从存储器读出的数据位数
  98.         Sda=1;
  99.         do{
  100.           Scl=0;
  101.           _nop_ ();
  102.           _nop_ ();
  103.           _nop_ ();
  104.           _nop_ ();
  105.           Scl=1;
  106.           _nop_ ();
  107.           _nop_ ();
  108.           _nop_ ();
  109.           _nop_ ();
  110.           if(Sda)      
  111.                 temp=temp|0x01;
  112.           else
  113.                 temp=temp&0xfe;
  114.           if(BitCounter-1)
  115.           {   temp1=temp<<1;       //逐位的读出
  116.               temp=temp1;
  117.           }
  118.           BitCounter--;
  119.         }while(BitCounter);   //读出8位后跳出循环
  120.         return(temp);         //返回读出的数据
  121. }
  122. void WrToROM(uchar Data,uchar Address)   //向存储器写一字节的数据 函数
  123. {
  124.      uchar i=0;
  125.    
  126.      Start();             //调用起始条件函数
  127.      Send(0xa0);       // 发送命令,准备写入数据到存储器,让存储器做好准备
  128.      Ack();            //  调用应答函数
  129.      Send(Address);    // 先发送要写入数据的的存储器内存地址
  130.      Ack();            // 调用应答函数
  131.    
  132.       Send(Data);      // 开始发送要写入到存储器中的数据
  133.         Ack();         // 调用应答函数
  134.   
  135.      Stop();           // 调用停止发送函数,表示发送完毕
  136. }
  137. uchar  RdFromROM(uchar Address)  //  从存储器读出一字节的数据
  138. {
  139.      uchar i;
  140.   
  141.         Start();                //调用起始条件函数
  142.         Send(0xa0);           //  让存储器准备接受命令
  143.         Ack();   
  144.         Send(Address);        //  发送要读出来的数据地址
  145.         Ack();
  146.         Start();              //   重新调用起始函数
  147.         Send(0xa1);          //   发送读出数据的命令
  148.         Ack();
  149.         i=Read ( );          // 开始读出数据
  150.         Scl=0;
  151.         NoAck();             // 读出数据成功。返回信号成功信号给存储器
  152.         Stop();
  153.     return (i);             //  返回读出的数据
  154. }


  155. uchar Key()                                    //键盘扫描子程序
  156. { uchar KValue;
  157. uchar tmp;
  158. P1|=0xff;   //将P1口的接键盘的位置1
  159. KValue=P1;
  160. KValue|=0x00;  //将未接键的位置1
  161. if(KValue==0xff) //
  162. return(0);  //返回
  163.   DelayMs(20);  //延时10ms,去键抖
  164. KValue=P1;
  165. KValue|=0x00;  //将未接键的位置1
  166. if(KValue==0xff) //位均为1,无键按下
  167. return(0);  //返回
  168.                         //如尚未返回,说明一定有1或更多位被按下
  169. for(;;)
  170. { tmp=P1;  
  171.   if((tmp|0x00)==0xff)
  172.    break;  //等待按键释放,防止按一次键盘,产生多次输入数据
  173. }
  174. return(KValue);          //返回按键值
  175. }

  176. Keyplay(uchar key)     // 按键值 处理函数
  177. { uchar password;        
  178.   
  179.    if (( key&0x80)==0)   //  按键值位7时的相应处理
  180.      { password=7;   
  181.       P0=DB_dat[7];      //  显示按键值,通过数码管显示
  182.   }
  183.    if (( key&0x40)==0)   //     按键值位6时的相应处理
  184.      { password=6;      
  185.       P0=DB_dat[6];      //     显示按键值,数码管显示
  186.   }
  187.    if (( key&0x20)==0)   //     按键值位5时的的相应处理
  188.       {password=5;
  189.       P0=DB_dat[5] ;     //     显示按键值
  190.   }
  191.    if (( key&0x10)==0)    //     按键值位4时的相应处理
  192.       {password=4;
  193.       P0=DB_dat[4];
  194.    }
  195.    if (( key&0x08)==0)    //     按键值位3时的处理
  196.       {password=3;
  197.       P0=DB_dat[3];
  198.    }
  199.    if (( key&0x04)==0)    //     按键值位2时的处理
  200.       {password=2;
  201.       P0=DB_dat[2];
  202.    }
  203.    if (( key&0x02)==0)
  204.       {password=1;
  205.       P0=DB_dat[1];
  206.    }
  207.    if (( key&0x01)==0)    //     按键值位0时的处理
  208.       {password=0;
  209.       P0=DB_dat[0];
  210.    }
  211.   
  212.     return password;     //返回输入的按键值
  213.      
  214.             
  215. }
  216. void Init()       //中断初始化
  217. {                  //定时器0工作于模式2
  218.      IT0=1;                    //负变跳电平有效
  219.   EX0=1;                    //开外部中断
  220.      EA=1;                      //开总中断
  221.    
  222. }

  223. void Init0() interrupt 0    //中断入口,中断后的程序处理 函数
  224. {                    
  225.    uchar k,j,key;
  226.    EX0=0;              //关闭中断,防止重复中断  ((重要 不可以把EX0=0;放在char k,j,key; 之前  否则将出现编译出错))
  227.    ch_pass=0;                //点亮红色发光二极管,显示当前处于密码修改状态 ,当输入8位密码后,取消密码修改状态
  228.    P0=0xff;                  //清空-数码管
  229.    cound=0;                  //清空密码输入个数标致,确保修改的密码个数从开始,直到输入8位密码后,再一次清0
  230.   while (1)
  231.    {  key=Key();             //调用键盘扫描程序,获取按键值
  232.       if (key)               //判断按键值是否位非0,非0代表有按键输入
  233.       { DB_inword[cound]=Keyplay(key);     //调用按键值处理程序,并且把按键输入的数字存放到 数组中
  234.      cound++;                           //  每输入一位的密码,COUND 自加
  235.         
  236.       if(cound==8)                     //  判断输入的密码个数是否到达8个
  237.     { cound=0;                       
  238.                                      //  密码输入个数已经到达8个
  239.            DelayMs(1000);
  240.    
  241.    
  242.                ch_pass=1;
  243.                DelayMs(700);
  244.                ch_pass=0;                  //  让红色发光二极管闪亮一次后,熄灭,表示密码已经成功输入8位
  245.                DelayMs(700);
  246.          ch_pass=1;

  247.       for(k=0;k<8;k++)               //   把输入的8位密码逐位的用数码管显示,并且写入到存储器中
  248.       { j=DB_inword[k];           //   断电后密码仍然保存起来,不会消失
  249.         P0=DB_dat[j];             //   获取数码管字符码,并且显示
  250.      DelayMs(1000);
  251.     WrToROM(j,k);                 //   写入密码到存储器,写入的内存地址为0~7
  252.         DelayMs(1000);
  253.           }
  254.              for(k=0;k<8;k++)
  255.                {   DB_password[k]=RdFromROM(k) ;}   
  256.          
  257.              P0=0xff;
  258.    break;                         //   密码修改成功后,跳出中断程序,返回主程序
  259.        }
  260.         }
  261.      
  262.   }
  263.    EX0=1;               //重新开启中断
  264. }

  265. void main ()                                //   主程序
  266. {
  267.    uchar i,j,key,pass=0;
  268.    Init();                                  //   中断初始化

  269.   
  270.    cound=0;
  271.   
  272.    for (i=0;i<8;i++)                       //   逐为的显示可以输入的密码值0~7,只能输入这8为有效数字
  273.    { P0=DB_dat[ i];
  274.      DelayMs(1000);
  275.   P0=0xff;
  276.    }
  277.   
  278.     for (i=0;i<8;i++)
  279.           { DB_password[ i]=RdFromROM(i) ; }      //从存储器读出密码值,并保存起来
  280.     while (1)                                 
  281. {    on=0;              
  282.          DelayMs(200);                           // 点亮右下脚的青色发光二极管,表明发光二极管在闪耀表明单片机在正常工作
  283.          on=1;
  284.          key=Key();                              // 获取按键值
  285.      if (key)                                 //  判断是否有按键按下
  286.       { DB_inword[cound]=Keyplay(key);           //  调用按键值处理函数,把输入的按键值保存起来  
  287.      cound++;                                 //  每输入一个值,自加1
  288.          xin=0;                                  //  显示当前处于密码输入状态,点亮左上脚的青色发光二极管
  289.       if(cound==8)
  290.     { cound=0;                             //   输入的密码个数到达8个后,进行密码验证
  291.                                             
  292.            DelayMs(1000);
  293.       
  294.      
  295.            xin=1;                           //   取消当前处于密码输入状态
  296.    
  297.              for (i=0;i<8;i++)        
  298.                   {   DelayMs(1000);
  299.             j=DB_inword[ i];         
  300.          P0=DB_dat[j];          //   逐位的显示输入的密码值,用送到P0口,数码管显示
  301.          DelayMs(1000);
  302.             if( DB_password[ i]==DB_inword[ i] )   //  逐位的验证输入的密码值是否和原始密码一致
  303.                                   { pass++;   }              //  输入的密码和原始密码一致是 变量PASS自加1
  304.                         
  305.                         if ( pass==8)                       //   PASS为8时,表明输入的密码和原始密码8位都一致
  306.                  {  xin_on=0;
  307.                                    DelayMs(10000);             //   密码完全正确,驱动继电器工作,将听到“嗒”的一声
  308.                                    xin_on=1;
  309.          
  310.                                 }
  311.                         }
  312.                   pass=0;                           //  清空验证位
  313.       P0=0xff;                          //  清空数码管
  314.                  for (i=0;i<8;i++)
  315.                     DB_inword[ i]=9;                 //  清空用于存放输入密码的数组,由于输入的密码限制在0~7之间                                    
  316.               }                                     //   9为无效的输入密码值。确保下次输入密码时,数组里边为无效值
  317.         }
  318.      }  
  319. }
复制代码
回复

使用道具 举报

ID:69843 发表于 2014-12-22 15:49 | 显示全部楼层
这不错,顶一下
回复

使用道具 举报

ID:72142 发表于 2015-1-13 14:29 | 显示全部楼层
很好,楼主的创意很棒
回复

使用道具 举报

ID:72778 发表于 2015-1-25 22:14 | 显示全部楼层
谢谢LZ分享
回复

使用道具 举报

ID:72570 发表于 2015-1-26 01:35 | 显示全部楼层
不错啊,我也想DIY一个试试
回复

使用道具 举报

ID:79544 发表于 2015-10-25 19:49 | 显示全部楼层
不错学习,数码管显示适合初学者。顶!
回复

使用道具 举报

ID:93926 发表于 2015-10-28 22:21 | 显示全部楼层
很好,楼主的创意很棒
回复

使用道具 举报

ID:148363 发表于 2016-11-16 22:26 | 显示全部楼层
支持支持 很好
回复

使用道具 举报

ID:148426 发表于 2016-11-17 11:19 | 显示全部楼层
这可是好东西,果断收藏了
回复

使用道具 举报

ID:148440 发表于 2016-11-20 17:23 | 显示全部楼层
顶一顶
回复

使用道具 举报

ID:150019 发表于 2016-11-24 23:44 来自手机 | 显示全部楼层
xiaoyao 发表于 2014-12-17 00:10
下面是源码预览

你好,我是个小白。没有黑币。如果你有这个压缩包的话能发到我的邮箱吗?846449482@qq.com 感激不尽
回复

使用道具 举报

ID:150019 发表于 2016-11-24 23:45 来自手机 | 显示全部楼层
Gameboy 发表于 2015-1-25 22:14
谢谢LZ分享

你好,我是个小白。没有黑币。如果你有这个压缩包的话能发到我的邮箱吗?846449482@qq.com 感激不尽
回复

使用道具 举报

ID:152043 发表于 2016-12-4 13:23 | 显示全部楼层
发的风格
回复

使用道具 举报

ID:130591 发表于 2016-12-9 15:18 | 显示全部楼层
谢谢分享,太好了!
回复

使用道具 举报

ID:153476 发表于 2016-12-9 15:49 | 显示全部楼层
看了一下 楼主专业知识很扎实
回复

使用道具 举报

ID:130231 发表于 2017-3-17 19:12 | 显示全部楼层
感谢你的分享
回复

使用道具 举报

ID:166459 发表于 2017-3-18 09:49 | 显示全部楼层

不错学习,数码管显示适合初学者。我也弄个试试顶!顶!顶!
回复

使用道具 举报

ID:233080 发表于 2017-9-29 14:52 | 显示全部楼层
这个程序很好,我试过了,非常实用,多顶顶
回复

使用道具 举报

ID:239797 发表于 2017-10-16 09:56 | 显示全部楼层
楼主仿真用的是Multisim么?
回复

使用道具 举报

ID:356193 发表于 2018-6-21 16:39 | 显示全部楼层
楼主厉害,学习
回复

使用道具 举报

ID:99130 发表于 2018-6-21 17:55 | 显示全部楼层
想知道怎么和锁连接
回复

使用道具 举报

ID:266164 发表于 2018-6-21 20:37 | 显示全部楼层
收下了。谢谢
回复

使用道具 举报

ID:356610 发表于 2018-6-22 14:50 | 显示全部楼层
好好研究研究
回复

使用道具 举报

ID:517951 发表于 2020-11-15 13:41 | 显示全部楼层
谢谢楼主分享,,51hei有你更精彩!!内容需要花时间消化
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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