找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机实现简单的密码锁设计思路与代码

[复制链接]
跳转到指定楼层
楼主
ID:758442 发表于 2020-5-22 16:19 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
1.     能设定一组4位的数字开启密码(设定密码功能)
2.     用LED小灯代替锁开启显示,输入密码正确,则小灯亮起(开锁功能)
3.     如果3次密码错误,则进行鸣叫报警,并在1分钟之内不能再次输入(报警功能)
4.     密码输入显示在数码管上,输入正确显示on,输入错误显示err(显示功能)
5.     可在以上功能上扩展。

整体要做的事情有:
1.初始化硬件
2.函数功能的实现
2.1按键扫描实现
2.2按键处理
2.3时间处理函数

设计思路为:先进行各种变量的初始化,然后循环执行三个子函数,其中在初始化函数里打开定时器,定时器装载初值溢出时间为2ms,进入中断执行一次数码管显示函数,由于人眼的余晖效应,人眼看到的是8个数码管持续同时亮,当有按键按下时则会进入按键扫描函数,继而得到键值进入按键服务函数,继而进入时间服务函数,由于定时器每2ms显示一次数码管,所以有按键按下时,可以及时的显示按键对应的操作

总结:做了一个简单的密码锁,主要的显示功能是用过定时中断进行操作的,其余的函数都是为了服务中断函数而设置的,对于最后的结果分析,达到了设计要求的基本功能,即设定密码功能、开锁功能、报警功能、显示功能。除此之外还增加了撤销功能,关闭和打开屏幕功能,确认功能修改密码功能以及其他小的细节功能。

单片机源程序如下:
  1. #include "reg52.H"
  2. #include "stdio.h"
  3. #include "intrins.h"

  4. unsigned char key_value;

  5. #define  DIG_SEG   P0//段选
  6. #define  DIG_PLA   P2//位选
  7. unsigned char code dig_tab[24] =//共阴数码管码表
  8. {
  9.                 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,//0、1、2、3、4、5、6、7、
  10.                 0x7f,0x6f,0x77,0x00,0x39,0x5e,0x79,0x71,//8、9、A、B、C、D、E、F、
  11.                 0x40,0x00,0x30,0x37,0x73,0x79,0x70//-,关,I,N,P,E,R
  12. };
  13. unsigned char dis_code[8] = 0;//显示数组
  14. unsigned char dig_show_tmp = 0;//显示临时变量

  15. unsigned char now_window;//当前显示窗口
  16. #define  inputpassword  10;//输入密码状态
  17. unsigned char password_now[7]={2,2,3,4,5,6};//输入当前密码保存数组
  18. unsigned char password[7]={1,2,3,1,2,3};//密码保存
  19. signed          char curr_bit;//输入当前位
  20. unsigned char curr_bit_tmp;//输入当前位备份
  21. unsigned char i;//临时计数变量
  22. unsigned char cnt_50ms;//中断50ms计数
  23. unsigned char time_50ms_flag;//50ms标志
  24. unsigned char open_del;//开锁成功延时计数
  25. unsigned char open_flag;//锁状态标志
  26. sbit relay = P1^0;//继电器
  27. /*******************************************************************************
  28. * 函 数 名         : delay_ms
  29. * 函数功能                   : 延时函数,延时1ms
  30. * 输    入         : cnt
  31. * 输    出         : 无
  32. * 说    名         : 该函数是在12MHZ晶振下,12分频单片机的延时。
  33. *******************************************************************************/
  34. void delay_ms(unsigned int cnt)   //
  35. {
  36.         unsigned int x;
  37.         for( ; cnt>0; cnt--)
  38.         {
  39.                 for(x=110; x>0; x--);//软件延时为1MS
  40.         }
  41. }
  42. /******************************************************
  43. ** 函数名:time_init
  44. ** 描述  :定时器初始化
  45. ** 输入  :无
  46. ** 输出  :无
  47. ******************************************************/
  48. void time_init(void)
  49. {
  50.           TMOD |= 0x01;//time0 工作方式为1
  51.           TH0 = 0xf8;//装载初值
  52.           TL0 = 0x2f;//装载初值,为2ms(65535-63535)
  53.       TR0 = 1;//开启定时器
  54.           ET0 = 1;//打开中断
  55.           EA=1;
  56. }
  57. /******************************************************
  58. ** 函数名:key_scan
  59. ** 描述  :按键扫描
  60. ** 输入  :无
  61. ** 输出  :无
  62. ******************************************************/
  63. void key_scan(void)
  64. {
  65.         static unsigned char key_in_flag = 0;//按键按下标志
  66.         unsigned char key_l,key_h;//存储扫描到行列值。
  67.         key_value = 20;//按键值清除
  68.         P3 = 0xf0;
  69.         if((P3 & 0xf0) != 0xf0)//按键按下
  70.         {
  71.                 delay_ms(5);//按键消抖动
  72.                 if(((P3 & 0xf0) != 0xf0) && (key_in_flag == 1))
  73.                 {
  74.                         key_in_flag = 0;//松手检测防止一直触发
  75.                         key_l = P3;//扫描得到行值
  76.                         P3 = 0x0f;
  77.                         key_h= P3;////扫描得到列值
  78.                         switch(key_l|key_h)
  79.                         {
  80.                                 //获取按键值
  81.                                 case 0xee:  key_value = 1;break;
  82.                                 case 0xed:  key_value = 2;break;
  83.                                 case 0xeb:  key_value = 3;break;
  84.                                 case 0xe7:  key_value = 10;break;

  85.                                 case 0xde:  key_value = 4;break;
  86.                                 case 0xdd:  key_value = 5;break;
  87.                                 case 0xdb:  key_value = 6;break;
  88.                                 case 0xd7:  key_value = 11;break;

  89.                                 case 0xbe:  key_value = 7;break;
  90.                                 case 0xbd:  key_value = 8;break;
  91.                                 case 0xbb:  key_value = 9;break;
  92.                                 case 0xb7:  key_value = 12;break;

  93.                                 case 0x7e:  key_value = 13;break;
  94.                                 case 0x7d:  key_value = 0;break;
  95.                                 case 0x7b:  key_value = 14;break;
  96.                                 case 0x77:  key_value = 15;break;
  97.                         }
  98.                 }
  99.         }
  100.         else
  101.         {
  102.                 key_in_flag = 1;//(按键松开标志)
  103.         }
  104. }
  105. void dis_dri(void)
  106. {

  107.                            static unsigned char dis_step = 1;
  108.                            DIG_SEG = 0x00;
  109.                            switch(dis_step)
  110.                            {
  111.                                   case 1:  //显示第1位
  112.                                   {
  113.                                            dig_show_tmp=dig_tab[dis_code[0]];

  114.                                                    DIG_SEG = dig_show_tmp;
  115.                                                    DIG_PLA = 0xfe;
  116.                                   }
  117.                                   break;
  118.                                   case 2:  //显示第2位
  119.                                   {
  120.                                            dig_show_tmp=dig_tab[dis_code[1]];

  121.                                                    DIG_SEG = dig_show_tmp;
  122.                                                    DIG_PLA = 0xfd;
  123.                                   }
  124.                                   break;
  125.                   case 3:  //显示第3位
  126.                                   {
  127.                                            dig_show_tmp=dig_tab[dis_code[2]];

  128.                                                    DIG_SEG = dig_show_tmp;
  129.                                                    DIG_PLA = 0xfb;
  130.                                   }
  131.                                   break;
  132.                   case 4:  //显示第4位
  133.                                   {
  134.                                            dig_show_tmp=dig_tab[dis_code[3]];

  135.                                                    DIG_SEG = dig_show_tmp;
  136.                                                    DIG_PLA = 0xf7;
  137.                                   }
  138.                                   break;
  139.                   case 5:  //显示第5位
  140.                                   {
  141.                                            dig_show_tmp=dig_tab[dis_code[4]];

  142.                                                    DIG_SEG = dig_show_tmp;
  143.                                                    DIG_PLA = 0xef;
  144.                                   }
  145.                                   break;
  146.                   case 6:  //显示第6位
  147.                                   {
  148.                                            dig_show_tmp=dig_tab[dis_code[5]];

  149.                                                    DIG_SEG = dig_show_tmp;
  150.                                                    DIG_PLA = 0xdf;
  151.                                   }
  152.                                   break;
  153.                   case 7:  //显示第7位
  154.                                   {
  155.                                            dig_show_tmp=dig_tab[dis_code[6]];

  156.                                                    DIG_SEG = dig_show_tmp;
  157.                                                    DIG_PLA = 0xbf;
  158.                                   }
  159.                                   break;
  160.                   case 8:  //显示第8位
  161.                                   {
  162.                                            dig_show_tmp=dig_tab[dis_code[7]];

  163.                                                    DIG_SEG = dig_show_tmp;
  164.                                                    DIG_PLA = 0x7f;
  165.                                   }
  166.                                   break;

  167.                            }
  168.                            dis_step++;
  169.                            if(dis_step>8)        //扫描完8个数码管后,重新从第一个开始扫描
  170.                            {
  171.                                   dis_step=1;
  172.                            }
  173. }
  174. /******************************************************
  175. ** 函数名:alm
  176. ** 描述  :定时闪烁函数
  177. ** 输入  : 无
  178. ** 输出  :无
  179. ** 调用  :中断调用
  180. ******************************************************/
  181. void time_service(void)
  182. {
  183.                 if(time_50ms_flag)//50ms时间到标志
  184.                 {
  185.                         time_50ms_flag = 0;//50ms时间到标志清零
  186.                         if (relay==0)//开锁后延时关锁
  187.                         {
  188.                                 open_del++;
  189.                                 if(open_del >= 20 * 5)        //5秒
  190.                                 {
  191.                                         open_del = 0;
  192.                                     relay = 1;   //关闭密码锁
  193.                                     dis_code[0] = 17;
  194.                                         dis_code[1] = 17;
  195.                                         dis_code[2] = 17;
  196.                                         dis_code[3] = 17;
  197.                                         dis_code[4] = 17;
  198.                                         dis_code[5] = 17;
  199.                                         dis_code[6] = 19;
  200.                                         dis_code[7] = 18;
  201.                                 }
  202.                         }
  203.                         if (open_flag)//输入错误显示
  204.                         {
  205.                                 open_del++;
  206.                                 if(open_del >= 20 * 2)
  207.                                 {
  208.                                         open_del = 0;
  209.                                         open_flag = 0;
  210.                                     relay = 1;   //关闭密码锁
  211.                                     dis_code[0] = 17;
  212.                                         dis_code[1] = 17;
  213.                                         dis_code[2] = 17;
  214.                                         dis_code[3] = 17;
  215.                                         dis_code[4] = 17;
  216.                                         dis_code[5] = 17;
  217.                                         dis_code[6] = 19;
  218.                                         dis_code[7] = 18;
  219.                                 }
  220.                         }
  221.                 }
  222. }
  223. /******************************************************
  224. ** 函数名:key_service
  225. ** 描述  :按键服务函数
  226. ** 输入  :无
  227. ** 输出  :无
  228. ** 调用  :主程序
  229. ******************************************************/
  230. void key_service(void)
  231. {
  232.                 switch (key_value)
  233.                 {
  234.                         case 1: case 2:case 3:
  235.                         case 4: case 5:case 6:
  236.                         case 7: case 8:case 9:case 0:
  237.                         {
  238.                                 password_now[curr_bit] = key_value;
  239.                                 if (++curr_bit>6)//输入6位密码
  240.                                 {
  241.                                         curr_bit = 6;
  242.                                 }
  243.                                 curr_bit_tmp = curr_bit;
  244.                                 for(i=0;i<curr_bit_tmp;i++)//显示
  245.                                 dis_code[i] = 16;//显示一杆
  246.                         }
  247.                         break;
  248.                         case 14://退格键#
  249.                         {
  250.                                 password_now[curr_bit] = 20;
  251.                                 if (--curr_bit<0)
  252.                                         curr_bit = 0;
  253.                                 dis_code[curr_bit] = 17;//不显示
  254.                         }
  255.                         break;
  256.                         case 15://按下确认键D
  257.                         {
  258.                                 if(
  259.                                         password_now[0] == password[0]&&
  260.                                     password_now[1] == password[1]&&
  261.                                         password_now[2] == password[2]&&
  262.                                         password_now[3] == password[3]&&
  263.                                         password_now[4] == password[4]&&
  264.                                         password_now[5] == password[5]
  265.                                   )//密码比较
  266.                                 {
  267.                                         dis_code[0] = 17;//输入正确open
  268.                                         dis_code[1] = 17;
  269.                                         dis_code[2] = 19;
  270.                                         dis_code[3] = 21;
  271.                                         dis_code[4] = 20;
  272.                                         dis_code[5] = 0;
  273.                                         dis_code[6] = 17;
  274.                                         dis_code[7] = 17;
  275.                                         relay = 0;
  276.                                 }
  277.                                 else//输入错误显示ERR
  278.                                 {
  279.                                         dis_code[0] = 17;
  280.                                         dis_code[1] = 17;
  281.                                         dis_code[2] = 22;
  282.                                         dis_code[3] = 22;
  283.                                         dis_code[4] = 21;
  284.                                         dis_code[5] = 17;
  285.                                         dis_code[6] = 17;
  286.                                         dis_code[7] = 17;
  287.                                         open_flag = 1;
  288.                                 }
  289.                                 for(i = 0;i < 6;i++)
  290.                                 {
  291.                                   password_now[i] = 0;
  292.                                   curr_bit = 0;
  293.                                   curr_bit_tmp = 0;
  294.                                 }
  295.                         }
  296.                         break;
  297.                         case 10://A设置密码
  298.                         {
  299.                                         password[0] = 2;
  300.                                         password[1] = 2;
  301.                                         password[2] = 2;
  302.                                         password[3] = 2;
  303.                                         password[4] = 2;
  304.                                         password[5] = 2;
  305.                         }
  306.                         break;
  307.                         case 11://B设置密码
  308.                         {
  309.                                         password[0] = 3;
  310.                                         password[1] = 3;
  311.                                         password[2] = 3;
  312.                                         password[3] = 3;
  313.                                         password[4] = 3;
  314.                                         password[5] = 3;
  315.                         }
  316.                         break;
  317.                         case 12://C设置密码
  318.                         {
  319.                                         password[0] = 4;
  320.                                         password[1] = 4;
  321.                                         password[2] = 4;
  322.                                         password[3] = 4;
  323.                                         password[4] = 4;
  324.                                         password[5] = 4;
  325.                         }
  326.                         break;

  327.                 }
  328. }
  329. /******************************************************
  330. ** 函数名:init_all_hardware
  331. ** 描述  :初始化所有硬件,及其变量参数。
  332. ** 输入  :无
  333. ** 输出  :无
  334. ** 调用  :主程序
  335. ******************************************************/
  336. void init_all_hardware(void)
  337. {
  338.                    delay_ms(100);
  339.                 time_init();//定时器初始化
  340.                 key_value = 20;
  341.         dis_code[0] = 17;
  342.                 dis_code[1] = 17;
  343.                 dis_code[2] = 17;
  344.                 dis_code[3] = 17;
  345.                 dis_code[4] = 17;
  346.                 dis_code[5] = 17;
  347.                 dis_code[6] = 19;
  348.                 dis_code[7] = 18;//显示IN
  349.                 now_window = inputpassword;//跳入输入密码
  350.                 cnt_50ms = 0;
  351.                 time_50ms_flag = 0;
  352.                 open_del = 0;
  353.                 relay = 1;
  354.                 curr_bit = 0;
  355.                 open_flag = 0;
  356. }
  357. void main(void)
  358. {
  359.          init_all_hardware();//初始化硬件,IO和定时器
  360.          while(1)
  361.          {
  362.                  key_scan();//按键扫描
  363.                  key_service();//按键服务处理函数
  364.                  time_service();//时间处理函数
  365.          }
  366. }
  367. /******************************************************
  368. ** 函数名:time0_interrupt
  369. ** 描述  :按键扫描函数
  370. ** 输入  :无
  371. ** 输出  :无
  372. ******************************************************/
  373. void time0_interrupt() interrupt 1
  374. {
  375.            TF0 = 0;//清除标志
  376.            TR0 = 0;
  377.            dis_dri();//动态扫描数码管
  378.            if (++cnt_50ms>25)
  379.            {
  380.                         cnt_50ms = 0;
  381.                         time_50ms_flag = 1;
  382.            }
  383.            TR0 = 1;
  384.            TH0 = 0xf8;
  385.            TL0 = 0x2f;//装载初值2ms(65535-63535)
  386. }
复制代码

所有资料51hei提供下载:
密码锁代码.rar (31.78 KB, 下载次数: 22)
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶1 踩
回复

使用道具 举报

沙发
ID:758442 发表于 2020-5-22 16:20 | 只看该作者
只是一个小设计,做的很水,算是达到了基本的要求,另外加了一些功能
回复

使用道具 举报

板凳
ID:663741 发表于 2020-5-27 11:32 | 只看该作者
有没有原理图?
回复

使用道具 举报

地板
ID:773272 发表于 2020-6-9 18:38 | 只看该作者
你这代码和你写的要求是一致的吗
回复

使用道具 举报

5#
ID:773272 发表于 2020-6-9 18:46 | 只看该作者
求和你的要求一致的仿真图和源代码
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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