找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1861|回复: 0
收起左侧

基于51单片机的电子密码锁程序Proteus仿真图设计

[复制链接]
ID:1049390 发表于 2022-10-28 16:14 | 显示全部楼层 |阅读模式
1、如果没有装KEIL软件:.c   .h结尾的文件即为程序,选择记事本或C语言软件打开。
2、若安装有KEIL软件:本程序有KEIL5设计,为避免版本区别带来的问题,建议使用KEIL5打开.uvproj结尾的工程文件。
3、其中,.hex结尾的文件为烧录文件,可以用于仿真和硬件实现。
注:其他文件为编译时自动生成的文件,不用管。

(1)仿真代码和源程序代码有着些许区别,做硬件烧录时请用文件夹1中的烧录程序(.hex);
(2)仿真请打开“电子锁仿真.DSN”工程文件,仿真代码请打开“project.uvproj”文件;
(3)仿真烧录时请打开“edoor.hex”文件;
(4)具体仿真功能为:
①输入密码,且输入的密码显示在液晶显示屏上;
②按下“DorBell”后,会响起门铃声;
③初始密码为“1234”,输入正确后,显示“OK”,并且LED灯闪烁,表示开门;
④输入密码错误后,显示“Eror”,三次输入错误后会报警;
⑤按下“DELE”,清楚输入的密码;
特别注意:本仿真原理图由protues8.7设计,为避免版本区别带来的问题,请尽量使用protues8.7打开仿真文件!!!

电子密码锁仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
51hei.gif

单片机源程序如下:
  1. /*
  2. 基于51单片机的电子密码锁设计
  3. 实现密码匹配,手动门铃等功能
  4. 设计人:讷言敏行
  5. 设计时间:2020.4.20
  6. */
  7. //库调用.宏类型定义.位定义//
  8. #include <reg52.h>                          
  9. //#include <intrins.h>
  10. #define uchar unsigned char
  11. #define uint unsigned int
  12. #define GPIO_KEY P1
  13. sbit RS = P2^2;                           //液晶显示器控制端口
  14. sbit RW = P2^3;
  15. sbit E = P3^7;
  16. sbit shuchu=P2^0;                          //继电器控制端口
  17. sbit beep=P2^1;                                  //报警器端口
  18. sbit DoorBell=P3^6;                          //门铃端口
  19. uchar upxs[16]={"Password:"}; //上排存放数组
  20. uchar dwxs[16]={""};          //下排存放数组
  21. int tempword[8]={0};                   //临时密码数组
  22. int password[8]={1,2,3,4};//初始密码
  23. uint now=0;                                          //数组等效指针
  24. uint key=0;                   //密钥
  25. uint KeyValue=16;             //用来存放读取到的键值
  26. uint warn=0;                                  //错误累计
  27. uint time=0;                                  //用于定时
  28. uint time1=0;                 //用于定时
  29. uint time2=0;                 //用于定时
  30. uint moshi=0;                                  //定时器内部模式
  31. //*********************************************************************************************************************************
  32. //液晶驱动显示模块//
  33. void delay(uint dell)//毫秒延时//
  34. {
  35.      uchar x;
  36.      for(dell;dell>0;dell--)
  37.      for(x=110;x>0;x--);
  38. }
  39. void wr_com(uchar temp)//写指令//
  40. {
  41.      RS=0;
  42.      RW=0;
  43.      P0=temp;
  44.      E=1;
  45.      E=0;
  46. }
  47. void wr_data(uchar num)//写数据//
  48. {
  49.      RS=1;
  50.      RW=0;
  51.      P0=num;
  52.      E=1;
  53.      E=0;
  54. }
  55. void disp_lcd(uchar addr,char *templ)//显示函数//
  56. {
  57.      uchar i;
  58.      wr_com(addr);
  59.          delay(50);
  60.      for(i=0;i<16;i++)
  61.     {
  62.      wr_data(templ[i]);
  63.          delay(50);
  64.     }         
  65. }
  66. void lcd_init()//初始化液晶//
  67. {
  68.      wr_com(0x30);
  69.      delay(50);
  70.      wr_com(0x38);
  71.      delay(50);
  72.      wr_com(0x01);
  73.      delay(50);
  74.      wr_com(0x06);
  75.      delay(50);
  76.      wr_com(0x0c);
  77.      delay(50);
  78. }
  79. void lcdxianshi(void)//液晶总显示//
  80. {
  81.      disp_lcd(0x80,upxs);
  82.      disp_lcd(0xc0,dwxs);
  83. }
  84. //*********************************************************************************************************************************
  85. //按键扫描模块//
  86. void Delay10ms(void)//延时函数//
  87. {
  88.     unsigned char a,b,c;
  89.     for(c=1;c>0;c--)
  90.         for(b=38;b>0;b--)
  91.             for(a=130;a>0;a--);
  92. }
  93. void KeyDown(void)//键盘检测函数//
  94. {
  95.         char a=0;
  96.         GPIO_KEY=0x0f;
  97.         if(GPIO_KEY!=0x0f)     //读取按键是否按下
  98.         {
  99.                 Delay10ms();       //延时10ms进行消抖
  100.                 if(GPIO_KEY!=0x0f) //再次检测键盘是否按下
  101.                 {
  102.                         
  103.                         //检测列
  104.                         GPIO_KEY=0X0F;
  105.                         switch(GPIO_KEY)
  106.                         {
  107.                                 case(0X07):        KeyValue=0;break;
  108.                                 case(0X0b):        KeyValue=1;break;
  109.                                 case(0X0d): KeyValue=2;break;
  110.                                 case(0X0e):        KeyValue=3;break;
  111.                         }
  112.                         //检测行
  113.                         GPIO_KEY=0XF0;
  114.                         switch(GPIO_KEY)
  115.                         {
  116.                                 case(0X70):        KeyValue=KeyValue;break;
  117.                                 case(0Xb0):        KeyValue=KeyValue+4;break;
  118.                                 case(0Xd0): KeyValue=KeyValue+8;break;
  119.                                 case(0Xe0):        KeyValue=KeyValue+12;break;
  120.                         }
  121.                         while((a<10)&&(GPIO_KEY!=0xf0))//按键松手检测
  122.                         {
  123.                                 Delay10ms();
  124.                                 a++;
  125.                         }
  126.                 }
  127.         }
  128. }
  129. //*******************************************************************************************************************************
  130. //数据处理模块//
  131. void keysend(void)//键值传递//
  132. {
  133.                   switch(KeyValue)
  134.               {
  135.                case 0:{dwxs[now]='0';tempword[now]=0;now++;break;}
  136.                    case 1:{dwxs[now]='1';tempword[now]=1;now++;break;}
  137.                    case 2:{dwxs[now]='2';tempword[now]=2;now++;break;}
  138.                    case 3:{dwxs[now]='3';tempword[now]=3;now++;break;}
  139.                    case 4:{dwxs[now]='4';tempword[now]=4;now++;break;}
  140.                    case 5:{dwxs[now]='5';tempword[now]=5;now++;break;}
  141.                    case 6:{dwxs[now]='6';tempword[now]=6;now++;break;}
  142.                    case 7:{dwxs[now]='7';tempword[now]=7;now++;break;}
  143.                    case 8:{dwxs[now]='8';tempword[now]=8;now++;break;}
  144.                    case 9:{dwxs[now]='9';tempword[now]=9;now++;break;}
  145.                    case 11:{
  146.                                      upxs[12]='S';
  147.                                   upxs[13]='U';
  148.                                   upxs[14]='R';
  149.                                   upxs[15]='E'; break;
  150.                    }
  151.                    case 15:{
  152.                           TR0=1;                     //定时器0打开
  153.                                      moshi=1;                         //模式1为门铃模式
  154.                                   KeyValue=16; break;//键值缓存清零
  155.                    }
  156.                   }
  157.                   if(now==8) now=0;          //只显示八位
  158. }
  159. void sure(void)//密码认证函数//
  160. {
  161.      uchar i;
  162.      if(KeyValue==11)
  163.          {
  164.              for(i=0;i<8;i++)
  165.                  {
  166.                          if(password[i]!=tempword[i])//对比密码
  167.                         {
  168.                             key++;
  169.                         }
  170.                  }                  
  171.                  if(key==0)                //密码正确,输出OK
  172.                            {
  173.                                 dwxs[13]='O';
  174.                                 dwxs[14]='K';
  175.                           shuchu=1;                  //开门
  176.                                 TR1=1;            //定时器1打开,启动倒计时
  177.                                 moshi=0;          //输入正确密码可关闭报警模式
  178.                                 beep=0;           //蜂鸣器复位
  179.                                 TR0=0;                          //并且关闭定时器0
  180.                            }
  181.                  if(key!=0)               //密码错误,次数累加
  182.                         {
  183.                                 dwxs[12]='E';
  184.                                 dwxs[13]='R';
  185.                                 dwxs[14]='O';
  186.                                 dwxs[15]='R';
  187.                                 warn++;
  188.                                 if(warn==3)                  //输入错误3次,报警
  189.                                 {
  190.                                    TR0=1;                  //定时器0启动
  191.                                moshi=2;                  //模式2启动报警
  192.                                    warn=0;                  //累计清零
  193.                                 }
  194.                         }
  195.          }
  196. }
  197. void delete(void)//清除函数//
  198. {
  199.      uchar i;
  200.              for(i=0;i<16;i++)
  201.                  {
  202.                     dwxs[i]=0x20;         //密码字符清零
  203.                  }
  204.                  for(i=0;i<8;i++)
  205.                  {
  206.                     tempword[i]=0;         //密码缓存数组清零
  207.                  }
  208.                     upxs[12]=0x20;   //SURE显示清零
  209.                         upxs[13]=0x20;
  210.                         upxs[14]=0x20;
  211.                         upxs[15]=0x20;
  212.                  now=0;                                 //类指针复位
  213.                  key=0;                                 //密钥清零
  214.                  KeyValue=16;                 //键值缓存清零
  215. }
  216. void condition_delete(void)  //条件清除
  217. {
  218.      if(KeyValue==10)
  219.          {
  220.                 delete();            //按下DELE键清除数据
  221.          }
  222.          KeyValue=16;                         //键值缓存清零
  223. }
  224. //********************************************************************************************************************************8
  225. //定时模块//
  226. void timer0() interrupt 1    //定时器0用于门铃
  227. {
  228.     switch(moshi)
  229.    {
  230.       case 1:{
  231.                 DoorBell=~DoorBell;
  232.             time++;
  233.              if(time<400)             //若需要拖长声音,可以调整 400 和 800
  234.             {
  235.                TH0=(8192-700)/32;     //700us 定时
  236.                TL0=(8192-700)%32;
  237.             }
  238.              else if(time<800)
  239.             {
  240.                TH0=(8192-1000)/32;    //1ms 定时
  241.                TL0=(8192-1000)%32;
  242.             }
  243.              else
  244.             {
  245.                time=0;                                  //计数清零
  246.                TR0=0;                                  //关闭定时器
  247.                            moshi=0;                                  //跳出模式1
  248.             }
  249.                         break;
  250.           }
  251.           case 2:{
  252.                            beep=~beep;
  253.                          time++;
  254.                          if(time<400)             //若需要拖长声音,可以调整 400
  255.             {
  256.                TH0=(8192-700)/32;     //700us 定时
  257.                TL0=(8192-700)%32;
  258.             }
  259.                         else
  260.                         {
  261.                            time=0;                                  //计数清零
  262.                         }
  263.                         break;
  264.           }
  265.    }
  266. }
  267. void timer1() interrupt 3          //定时器1用于自动关门
  268. {  
  269.     TH0=(65536-50000)/256;  
  270.     TL0=(65536-50000)%256;  
  271.     time1++;   
  272.     if(time1==20)//一秒  
  273.     {      
  274.       time2++;
  275.           time1=0;  
  276.     }
  277. }
  278. //**********************************************************************************************************************************
  279. //主函数//
  280. void main(void)//主函数
  281. {
  282.     TMOD=0x10;                                  //0001 0000//定时器1方式1,定时器0方式0
  283.         TH0=(8192-700)/32;                 //定时器0 700us 定时
  284.     TL0=(8192-700)%32;
  285.     TH1=(65536-50000)/256;   //定时器1 50ms
  286.     TL1=(65536-50000)%256;  
  287.     EA=1;  
  288.     ET0=1;
  289.         ET1=1;
  290.     shuchu=0;                            //门锁初始化
  291.         beep=0;                                    //警报初始化
  292.         DoorBell=0;                                //门铃初始化
  293.     lcd_init();                            //液晶初始化
  294.         while(1)
  295.         {
  296.                 KeyDown();                    //按键检测
  297.                 keysend();                    //数据传递
  298.                 lcdxianshi();            //输入显示
  299.                 sure();                            //密码认证
  300.                 condition_delete(); //按键清除
  301.                 if(time2==4)            //门锁打开后4秒关闭
  302.                 {
  303.                    shuchu=0;
  304.                    time2=0;
  305.                    delete();                //自动清除
  306.                    TR1=0;                 //关闭定时器1
  307.                 }               
  308.         }                                
  309. }
复制代码
Keil代码与Proteus仿真下载:
基于51单片机的电子密码锁设计.7z (2.39 MB, 下载次数: 89)

评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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