基于51单片机的数码管密码锁

基于51单片机的数码管密码锁是一种可以设置密码并通过输入密码来解锁的安全装置。该密码锁使用51单片机作为控制主板,配合数码管显示模块、按键模块和电磁锁等元件实现密码锁的功能。

实现步骤如下:

1. 硬件连接:将51单片机与数码管、按键模块和电磁锁等元件进行连接。数码管用于显示密码和解锁状态,按键模块用于输入密码,电磁锁用于控制门锁的开关。

2. 程序设计:使用汇编或C语言编写程序。程序主要包括密码的设置、密码的输入和验证等功能。在密码设置模式下,用户可以通过按键输入密码并保存到EEPROM中。在密码输入模式下,用户可以通过按键输入密码并与EEPROM中保存的密码进行比对,如果密码匹配则解锁电磁锁,否则显示密码错误。

3. 系统测试:将程序烧录到51单片机中,将系统连接好后进行测试。测试过程中,可以尝试设置密码、输入密码并观察系统的响应情况。

需要注意的是,为了增加密码的安全性,可以在程序设计中加入防止密码破解的措施,例如密码错误次数的限制、密码输入超时等。此外,还可以考虑使用其他安全元件,如指纹识别模块或刷卡模块,以提高密码锁的安全性。

  • 数字密码锁的基本原理 

51单片机数码管密码锁的基本原理是将用户输入的密码与初始的密码进行比较,如果两者匹配则开锁,否则关锁,开锁之后可以进行修改密码。选用单片机开发板STC89C52作为本设计的核心元件,利用编程设计、I/O端口及其板上的数码管、按键等各种硬件电路,设计密码锁功能,以自创的代码将功能实现。利用单片机的矩阵键盘用于密码的输入、密码复位和更改密码的控制,不掉电密码的存储以及使用数码管进行实时显示输入的密码。数码管负责实现密码显示,矩阵按键负责密码的输入、更改以及复位。

  • 数字密码锁的硬件设计   

(一)原理图设计

图1  数字密码锁原理图

(二)原理图各部分原理

主控制电路是由STC89C52芯片和12M晶振组成的,重要的功能是通过写入代码来控制P1、P2、和P3口输入输出状态,达到控制整个电路的功能。

复位按键电路是由复位按键和电容组成的,当复位按键按下之后RES会被拉高,STC89C52芯片上面的RES接口会被给高电平,达到复位电路的功能。

矩阵按键电路是由十六个按键组成,使用一个4行4列矩阵结构,其中每一行都连接一个可编程I/O口,每一列连接一个按键开关。当按下某个按键时,可编程I/O口的输入由高变低,此时通过扫描这4行4列的矩阵可以得出按键对应的行和列号。

数码管显示电路是由两个四位数共阳极码管组成,是一种常用的显示和控制电路,它可以显示不同格式的数字和字母,以及相应的图形。数码管电路由51单片机主控,数码管位选连接到单片机的输出口P2,数码管段选连接到单片机的输出口P3,信号经过电路驱动,在一定时间内控制一个数码管显示相应的状态,然后通过快速切换使的人眼观测为几个数码管同时点亮。

序号

器件名称

参数

数量

1

USB座

1

2

USB线

1

3

串口下载线

1

4

104电容

0.1uF

7

5

LED灯

1

6

电阻

2K

1

7

蜂鸣器

1

8

STC89C52

1

9

晶振

12MHz

1

10

按键

16

11

复位键

1

12

电阻

10K

1

13

40针座

1

14

三极管9015

9

15

电阻

330

1

16

16针座

1

17

MAX232

1

18

电容

20pF

2

19

4位LED

2

20

电阻

330

8

21

电阻

4.7K

8

表2    元器件清单

  • 数字密码锁的软件设计

程序流程图如下:

程序代码如下:

#include <REGX52.H>

typedef unsigned int u16; //对系统默认数据类型进行重定义

typedef unsigned char u8;

#define KEY_MATRIX_PORT P3 //使用宏定义矩阵按键控制口

#define SMG_A_DP_PORT P0 //使用宏定义数码管段码口

//共阳极数码管显示0~9 N F 的段码数据

u8 nixie[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x37,0x71};

unsigned int Code = 0;//用于保存密码的变量

unsigned int TempCode = 0;//用于暂时保存密码的变量

unsigned int NewCode = 0;//用于保存新密码的变量

unsigned int LNew=0,New=0;//用于判断是否开始录入新密码

unsigned int Newlate=0;//用于确定是否新密码录入结束

void wei(unsigned char pizz);//用于显示第几个数码管的函数声明

unsigned int key=0;//保存按键按下的位数

unsigned int T=0;//密码输入正确判断

unsigned int TLL=0;//密码输入正确判断

unsigned int F=0;//密码输入错误判断

static unsigned char i = 0;//刷新数码管

void delay_10us(u16 ten_us)//延时函数

{

while(ten_us--);

}

u8 key_matrix_ranks_scan(void)

{

u8 key_value=0;



KEY_MATRIX_PORT=0xf7;//给第一列赋值0,其余全为1

if(KEY_MATRIX_PORT!=0xf7)//判断第一列按键是否按下

{

delay_10us(500);//消抖

switch(KEY_MATRIX_PORT)//保存第一列按键按下后的键值

{

case 0x77: key_value=1;break;

case 0xb7: key_value=5;break;

case 0xd7: key_value=9;break;

case 0xe7: key_value=13;break;

}

}

while(KEY_MATRIX_PORT!=0xf7);//等待按键松开



KEY_MATRIX_PORT=0xfb;//给第二列赋值0,其余全为1

if(KEY_MATRIX_PORT!=0xfb)//判断第二列按键是否按下

{

delay_10us(500);//消抖

switch(KEY_MATRIX_PORT)//保存第二列按键按下后的键值

{

case 0x7b: key_value=2;break;

case 0xbb: key_value=6;break;

case 0xdb: key_value=10;break;

case 0xeb: key_value=14;break;

}

}

while(KEY_MATRIX_PORT!=0xfb);//等待按键松开



KEY_MATRIX_PORT=0xfd;//给第三列赋值0,其余全为1

if(KEY_MATRIX_PORT!=0xfd)//判断第三列按键是否按下

{

delay_10us(500);//消抖

switch(KEY_MATRIX_PORT)//保存第三列按键按下后的键值

{

case 0x7d: key_value=3;break;

case 0xbd: key_value=7;break;

case 0xdd: key_value=11;break;

case 0xed: key_value=15;break;

}

}

while(KEY_MATRIX_PORT!=0xfd);//等待按键松开



KEY_MATRIX_PORT=0xfe;//给第四列赋值0,其余全为1

if(KEY_MATRIX_PORT!=0xfe)//判断第四列按键是否按下

{

delay_10us(500);//消抖

switch(KEY_MATRIX_PORT)//保存第四列按键按下后的键值

{

case 0x7e: key_value=4;break;

case 0xbe: key_value=8;break;

case 0xde: key_value=12;break;

case 0xee: key_value=16;break;

}

}

while(KEY_MATRIX_PORT!=0xfe);//等待按键松开



return key_value;

}

u8 key_matrix_flip_scan(void)

{

static u8 key_value=0;



KEY_MATRIX_PORT=0x0f;//给所有行赋值0,列全为1

if(KEY_MATRIX_PORT!=0x0f)//判断按键是否按下

{

delay_10us(500);//消抖

if(KEY_MATRIX_PORT!=0x0f)

{

KEY_MATRIX_PORT=0x0f;//测试列

switch(KEY_MATRIX_PORT)//保存行为0,按键按下后的列值

{

case 0x07: key_value=1;break;

case 0x0b: key_value=2;break;

case 0x0d: key_value=3;break;

case 0x0e: key_value=4;break;

}

KEY_MATRIX_PORT=0xf0;//测试行

switch(KEY_MATRIX_PORT)//保存列为0,按键按下后的键值

{

case 0x70: key_value=key_value;break;

case 0xb0: key_value=key_value+4;break;

case 0xd0: key_value=key_value+8;break;

case 0xe0: key_value=key_value+12;break;

}

while(KEY_MATRIX_PORT!=0xf0);//等待按键松开

}

}

else

key_value=0;

return key_value;

}

void smg_display(unsigned char pizz)

{

    switch(pizz)//位选

{

case 1: P2=0x7f;break;//第一个灯亮

case 2: P2=0xbf;break;//第二个灯亮

case 3: P2=0xdf;break;//第三个灯亮

case 4: P2=0xef;break;//第四个灯亮

case 5: P2=0xf7;break;//第五个灯亮

case 6: P2=0xfb;break;//第六个灯亮

case 7: P2=0xfd;break;//第七个灯亮

case 8: P2=0xfe;break;//第八个灯亮

}

}

void main()

{

  unsigned char k;//限制按下次数

while(1)

{

  key=key_matrix_ranks_scan();

  if(key!=0)

 {

         if(key<=10)

         {

           if(k<4)

            {

 if(T==0)

 {

               Code*=10;            

               Code+=key%10;

  if(TLL!=1)

{

                    k++;

}

 }

if(TLL==1)

{

    TempCode*=10;            

             TempCode+=key%10;

Code=TempCode;

             k++;

     LNew=1;

T=0;

}

         }    

else

{

 k=0;

  if(Code==8888&&Newlate==0)

  {

T=1;

Code=8888;

TLL=1;

   }

  else if(Code==NewCode&&Newlate==1)

  {

   T=1;

   LNew=0;

   TLL=0;

  }

       else

 {

  F=1;

 }

  }

            }

            else if(key==16)

            {

                k=0;

                Code=0;

T=0;

  F=0;

  LNew=0;

  New=0;

            }

            else if(key==15)

            {

               if(LNew==1)

  {

 NewCode=TempCode;

Newlate=1;

 TLL=0;

 Code=0;

 k=0;

 }

            }

        }



if(F==0&&T==0&&Code!=0)

    {

   for(i=0;i<8;i++)

      {

   switch(i)

        {  

        case 0:smg_display(1);P0=~nixie[Code/1000%10];break;

        case 1:P0=0xff;break;

        case 2:smg_display(3);P0=~nixie[Code/10%10];break;

        case 3:P0=0xff;break;

        case 4:smg_display(2);P0=~nixie[Code/100%10];break;

        case 5:P0=0xff;break;

        case 6:smg_display(4);P0=~nixie[Code%10];break;

        case 7:P0=0xff;break;

        }

delay_10us(50);

   }

}

 if(T==1&&LNew==0)

 {

 for(i=0;i<5;i++)

     {

    switch(i)

        {  

case 0:P0=0xff;break;

        case 1:smg_display(7);P0=~nixie[0];break;

        case 2:P0=0xff;break;

case 3:smg_display(8);P0=~nixie[10];break;

        case 4:P0=0xff;break;

        }

delay_10us(50);

}

}

 if(F==1)

 {

 for(i=0;i<7;i++)

     {

   switch(i)

       {  

case 0:P0=0xff;break;

        case 1:smg_display(6);P0=~nixie[0];break;

        case 2:P0=0xff;break;

case 3:smg_display(7);P0=~nixie[11];break;

        case 4:P0=0xff;break;

case 5:smg_display(8);P0=~nixie[11];break;

        case 6:P0=0xff;break;

       }

delay_10us(50);

 }

 }

 if(Code==0)

{

  P0=0x00;  //未输入密码  数码管全部不亮

}

    

}

}
  • 设计成果

矩阵按键功能图如下:

下载好程序之后随便按下四个密码,这里以按下按键key1、key2、key3、key4为例,数码管显示输入的密码1234如图一;密码输入达到四位后,此时再按下任一按键,如果密码不是初始密码8888,数码管则显示OFF如图二。此时按下按键key13进行复位,复位后可以继续输入密码,此时这里输入密码为8888和初始密码一样如图三,再按下任一按键,数码管显示ON如图四;当输入密码正确后,可以选择按下复位按键后继续输入密码,或者选择更换密码,这里由key5、key6、key7、key8组成新密码5678,再按下key14保存新密码,这样密码锁的密码就由初始密码8888变成了5678,可以继续分别输入密码8888和5678进行验证如图五和六。

                         图一                                 图二

                                              图三                                            图四

                                    图五                                                                图六

设计总结

首先,我要感谢老师在本门课程中给我们提供的宝贵教学资源和丰富的教学经验。此外,我也要感谢队友在完成课程设计任务时的合作精神和出色表现,使我们最终能够顺利完成课程设计任务。在课程设计的过程中,我们学习了关于单片机的例如数码管、延时设计、按键消抖等知识,并用实际应用来进行综合考核。通过本次课程设计,我深刻地理解到,单片机可以实现各种功能,也因为其小巧、低功耗的特点,在大型项目中也能放大作用。最后,我想强调一下,要善于总结、吸收、思考,努力将所学融会贯通,以更好地实现自身的发展和进步。

猜你喜欢

转载自blog.csdn.net/qq_58404700/article/details/131486942