视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
单片机电子密码锁课程设计.doc
2025-09-30 22:44:42 责编:小OO
文档
基于单片机的电子密码锁设计

一、设计要求和条件

 1.1 设计要求 

 根据单片机开发板所提供的元件特性和硬件电路,编写相关的程序,通过实验开发板实现电子密码锁在LCD1602上显示的功能。

1.搭建proteus仿真电路图平台,模拟单片机要实现的功能;

2.焊接单片机系统开发板;

3.编写程序,实现密码锁相关功能;

4.下载并调试程序,实现密码锁的具体功能。

  1.2 设计目的

1.熟练掌握KEIL软件的使用方法;

2.熟练掌握PROTEUS软件的使用方法;

3.掌握单片机I/O接口的工作原理;

4.掌握中断系统的工作原理;

5.掌握液晶LCD1602的工作原理及编程方法;

6.掌握蜂鸣器的编程使用;

7.掌握行列式键盘的工作原理及编程使用方法;

8.掌握单片机的ISP下载使用方法。

  1.3 功能概述

本设计是基于单片机的密码锁设计方案,根据要求,给出了该单片机密码锁的硬件电路和软件程序,同时给出了硬件设计方案、软件流程图、C语言源程序及详细注释等内容,由于单片机实验板上的矩阵键盘为3*3的,则规定0-5号键为数字键,6-8号键为功能键,其中该密码锁的具体功能介绍如下:

(1)按“8”号键则输入密码,初始密码为012345,在LCD1602上显示密码值为“******”(密码是保密的),输完6位后键盘就锁定,在LCD1602上显示密码是否正确,若输入的密码长度小于6位,则1602等待密码输入。

(2)若密码输入正确后,则绿色的发光二极管亮表示开锁,并且1602上显示“you are right!”,等待是否修改密码。

(3)密码输入错误时显示“code is wrong”,接着会给你第二、第三次机会输入密码,如果三次密码都错误时,发出“叮咚”的报警声,且红色报警指示灯不停闪烁,按复位键清除报警。

 按“7”号键表示若密码不小心输入时,可以删除输入错误的密码。

 (5)按“6”修改密码,要求输入原密码是正确的,然后按该键后,蓝色密码修改指示灯会亮,并且1602上会显示“Input new code”,输入正确要求再次输入,两次输入一致提示“Modify right!!!”并返回主菜单。两次不一致时提示“Modify error!!!”,然后返回主菜单。

二、硬件设计方案的论证

本系统整体主要划分为五大模块,分别是由单片机最小系统、矩阵键盘、LCD显示、报警系统、指示灯电路等组成。单片机系统主要功能是对外部输入的数据进行处理,显示电路将所要操作的步骤显示出来,指导用户使用,报警电路是对输入错误密码时的警告报警。系统能完成开锁、密码输入错误报警、密码删除、修改用户密码基本的密码锁的功能。若依据实际的实验板情况还可以添加遥控和掉电保护功能。

  2.1 总体方案设计

本设计的具体总模块设计方案如下图(1)所示

 图(1) 硬件总方案模块框图

2.2 具体模块方案的设计

1.主控芯片的方案选择

  方案一:采用硬件电路进行电子密码锁设计,比如使用 74LS112 双 JK 触发器构成的数字逻辑电路控制方案,该种方案可以实现基本功能,而且优点是不需要软件编程,但电路连接比较复杂,关键在于不易实现自行设置密码的要求。

方案二:单片机中的STCC51是具有高性能和低功耗优点的8位可编程控制器,内核具有丰富的指令集和32个通用工作寄存器,可以通过软件编程来实现电子密码锁设计中的各项要求和功能,而且单片机的 I/O 口也足够使用,硬件电路连接比较简单。

综上所述方案论证,本次电子密码锁系统设计的主控芯片选择 STC单片机的 STCC51来完成,采集输入数据对其处理并发出相应的指令。

2.键盘模块方案选择

  方案一:可以选择连接式键盘。对于连接式键盘,其每个键都的接入一根数据线,平时所有的数据线都被连接成高电平,当任何一个键按下时,与之相连的数据线将被拉成低电平。这种方案在处理多个数据时编程和硬件连接电路会较复杂。

方案二:选择矩阵行列式键盘作为输入模块。矩阵式行列式键盘由行线和列线组成,按键位于行、列的交叉点上,行、列分别连接到按键开关的两端,列线通过上拉电阻接到高电平。无按键动作时,列线处于高电平状态;有按键按下时,交点的行线列线接通,列线电平状态将由与此行线相连的行线电平决定。本次通过键盘输入的值有很多种,而矩阵式键盘节省了好多的 I/O 口,适用于按键数量较多的场合。

综上且根据本次设计中的单片机实验板选择使用3*3矩阵键盘来完成输入密码值,此种键盘功能简单实用,如下图(2)所示

 

 图(2)矩阵键盘

3.显示模块方案选择

方案一:采用 LCD1602 作为主液晶显示器。此液晶屏能输入两行的字母或数字,功能比较简单,比较通用。本次设计中要显示输入密码的数据值和各功能的提示,使用 LCD1602 液晶来作为显示模块较直观形象。如图(3)所示,显示比较直观形象

   图(3) LCD1602显示

方案二:采用数码管来实时显示输入密码的数值,由于密码的个数为6硬件电路连接线路较复杂,连接管脚较多,而且观看起来不清晰、直观。

基于以上两种方案比较,本次设计中采用方案一。

4.报警模块方案的选择

方案一:采用1602显示特殊数字或字母来表示输入密码正确或者错误,这种方案也可以直观表示。

 方案二:采用声和光两种方式的双重效果进行报警,如果密码输入错误报警灯闪烁而且蜂鸣器会报警,这样就能多角度进行密码错误报警。

经过上述分析比较,使用方案二的声光报警来表示解锁失败,如图(4)所示

 图(4)  报警电路设计

5.报警解除模块

该模块用单片机最小系统中的复位功能,既可以节省了I/O管脚,还可以重新开始输入密码,此模块中的蜂鸣器的功能是当用户输入密码错误的次数超过了3次,蜂鸣器鸣笛报警,键盘处于锁定状态其电路图如图(5)所示

 图(5)复位电路

三、软件设计

 软件的设计主要有主程序模块,键盘扫描模块,LCD1602显示模块,密码比较模块,开锁程序模块、报警模块等。

  3.1 主程序模块

主程序主要完成LCD初始化、检查有无按键按下、以及调用显示、密码修改程序等等。主程序的流程图如图(6)所示

                                           图(6)主程序方框图

3.2 开锁程序模块

开锁程序流程图如图(8)所示。

  图(7) 开锁子程序模块

3.3 LCD1602显示模块

本系统使用LCD1602实现显示,参照LCD1602的使用手册进行初始化和程序编写就可以显示,即在程序编写中添加LCD1602的驱动程序。这里的驱动程序主要包括:初始化函数、设置显示坐标、写字符函数及写字符串函数。在时钟界面时显示时间的运行,在密码锁界面时主要显示提示信息和输入的密码,当然,当输入密码数字时,输出不是显示数字,而是用“*”显示代替。LCD1602的部分读写控制时序程序如下图(8)所示:

                              图(8)LCD1602初始化

3.4 键盘扫描与处理模块

 该模块具备功能有:逐列扫描键盘确实被按键的具体位置、判断键盘上有无键按下、消除抖动、判断闭合的键是否释放等功能,该模块利用case语句来判断按键的按下与否,方法是:依次给行线送低电平,然后查所有列线状态,如果全为1,则所按下的键不在此列;如果不全为1,则所按下的键必在此列,而且是在与零电平行线相交的交点上的那个键。先给P2口赋值为fe,再对P2口扫描,再与f8相与,看是否相等,若等,则无键按下,不等,则有键按下,再判断在哪列。然后进行按键处理函数,其处理函数的流程图如图(9)所示

    图(9)按键功能程序

四、系统调试

4.1 调试部分

 采用先分别调试各单元模块,调通后再进行整机调试的方法,以提高调试效率。

(1)键盘测试  在带有单片机的电路板上编程调试3*3矩阵键盘,使其在液晶上显示出键盘锁对应的数字及功能。利用仿真机调试成功后通过编程器将程序写入芯片中调试。

(2)报警及开锁控制电路测试 通过矩阵键盘控制输入正确的开锁密码,锁灯亮;当连续输入三次的密码错误时,报警指示灯闪烁,蜂鸣器报警并锁死键盘。

(3)显示电路测试 通过电位器对1602液晶的对比度和背光灯进行调整,使其在最适合的状态下工作。

各功能模块均调通后,进行整机调试,其过程如下:将调好的各功能模块连接在一起,用函数信号发生器模拟电压信号,先用仿真机代替STCC51 单片机进行模拟调试,对每一芯片的片选、启动进行检测,并对数据线也进行检测。调试成功后再将程序写到单片机中进行调试。

4.2 软件调试部分

  (1)KEI的编程,仿真,编译集成环境KEILUV3:将汇编语言源程序编译成*.hex文件。

(2)STC-ISP-V4.83下载器:将C语言源程序编译成的*.hex文件在线下载到STC单片机中。

(3)STC-ISP-V4.83使用说明:

 双击图标并出现下图画面

(II)选择你需要的单片机型号;

(III)打开“001.HEX”文件;

(IV)选择你的串行口,这里选择COM1;

(V)点击download/下载,即可实现自动下载编程。

4.3 调试结果分析

本系统以STCC51 为核心部件,利用软件模块化编程,通过键盘控制和液晶显示实现了密码锁的功能、报警功能,并能防止多次试探密码,能实现本设计题目的基本要求。在设计时根据实验板的硬件连接尽量做到硬件电路简单稳定、减小电磁干扰和其他环境干扰,充分发挥软件编程的优点,减小因元器件精度不够引起的误差。本设计成功仿真实现了1602液晶显示、密码“*”的设置、密码设置,防止多次试探,报警等功能。并且采用C语言编写程序,具有很强的移植性,为系统增减和修改带了方便。

在设计中也遇到了许多困难,例如对LCD1602的具体功能不熟悉,于是就在图书馆,网上收索相关资料来进行编程,对其功能模式有了进一步的理解。还有对3*3键盘扫描程序的编程,利用学过的4*4键盘编程的原理方法用了case语句来对其编程。

由于时间有限和自身知识水平的,本系统还存在一些不够完善的地方,要作为实际应用还有许多具体细节问题需要解决。例如:扩展AT2402模块储存密码,红外报警探测技术,密码指纹识别技术,语音识别技术,图像识别技术等等。只有这样更能满足社会的发展和人民的需求。

五、模拟仿真结果

 各模块的仿真结果如下图所示

  图(10) Welcome界面

                                     图(11)输入密码界面

             图(12)开锁界面

                              图(13)修改密码界面

                               图(14)密码修改成功界面

                               图(15)报警界面  

六、设计心得

这次实训的时间为两周,分三个阶段:第一,做电路仿真,原理图;第二,对单片机实验板进行焊接;第三,电路硬件调试。每一步都很认真做了,仿真还是第一次用到实际中,感觉有很大的收获。一般一次成功的板子是很少的,都要进过调试查错才可以得到一块完整的电路板。

这一次做的电子密码锁及LCD显示。原理看似简单,但过程让我深深感受到再简单的电路图,理论与实际有一定的差入。在参考书的原理图经过了个人的改进,让功能更完善,特别是程序的调试,花的时间做多,也是最难的一个地方。我们最终的目的是应用而不是理论结果。我们学的理论知识都是比较先进的,但是由于平常少于把知识付诸于实践。

通过本次设计,培养了创新意识和综合素质,更好地掌握了电子产品设计与制作的工艺和流程,提高个人基本能力、实验及设计能力和工作能力,基本知识更加牢固,会看图、会焊接安装、会测量、会查资。

七、参考文献

[1] 杭和平. 单片机原理与应用. 北京:机械工业出版社,2008

[2] 李朝青. 单片机原理与接口技术.北京:航空航天出版社,2009

[3]宋彩利.单片机原理与C51编程 [M].  西安交通大学出版社,2007

附录I  proteus仿真图

附录II  实物显示

 附录III  源程序

#include

#define ulong unsigned long

#define uint unsigned int

#define uchar unsigned char

uchar temp,num,flag,r;

uchar code table1[]=" welcome!(^_^)";//主界面

uchar code table2[]="liu hai yan DIY";//主界面

uchar code table3[]="******";//密码显示“******”

uchar code table4[]="code is wrong!";//密码错误显示

uchar code table5[]="you are right!";//开锁显示

uchar code table6[]="the second time!";//第二次开锁显示

uchar code table7[]="the last time!";//第三次开锁显示

uchar code table8[]="Input new code:";//修改密码显示

uchar code table9[]=" calling....";//报警显示

uchar code table12[]="Modify right!!!";//修改密码正确

uchar code table10[]="password:";//输入密码

u//删除密码显示

uchar code table13[]="Input again:";//再次输入密码

uchar code table14[]="Modify error!!!";//修改密码错误

uchar  init_pswd[6]={0,1,2,3,4,5};//初始化密码

uchar  pswd[6]={0}; //放新修改的输入的密码

sbit lcdrs=P1^0; // LCD 数据/指令(H/L)选择端

sbit lcdrw=P1^1;

sbit lcden=P1^2;  //LCD使能

sbit  P1_3=P1^3;//开锁指示灯

sbit  P1_4=P1^4;//修改密码指示灯

sbit  P1_5=P1^5; //报警指示灯

sbit P2_7=P2^7;  //蜂鸣器

/*****************************************子函数声明*/

void delay(uint z);

void init();//初始化子函数

void write_com(uchar com);//写指令子函数

void write_data(uchar dat1);//写数据子函数

uint keyscan();

void mima();//密码处理子函数

void mima1();  //修改密码函数

void Alarm(uchar t);//报警函数

/************************************************液晶驱动*/

void init()

{  lcden=0; 

 write_com(0x38);  //设置1602显示,5x7点阵显示,8位数据接口 write_com(0x0e); //00001DCB,D(开关显示),C(是否显示光标),B(光标闪烁,光标不显示)  

 write_com(0x06);  //000001N0,N(地址指针+-1)

 write_com(0x01);  //清屏指令  每次显示下一屏内容时,必须清屏

 write_com(0x80);  //第一行显示  

}

void write_com(uchar com) 写命令子函数 

 { lcdrs=0; 低电平选择为 写指令 

 lcdrw=0;

 P0=com; 把指令写入P0口 

 delay(5);  

 lcden=1; 开使能 

 delay(5);  //读取指令  

 lcden=0;  //关闭使能

 }

void write_data(uchar dat1) 写数据子函数  

{  lcdrs=1; 高电平选择为写数据 

 lcdrw=0;

 P0=dat1; 把数据写入P0口

 delay(5);

 lcden=1; 开使能 

 delay(5); 读取数据 

 lcden=0; 关闭使能 

}

void delay(uint z) 延时子函数  z*1ms 

{  uint x,y;

 for(x=z;x>0;x--)

  for(y=110;y>0;y--);

}

uint keyscan() 键盘扫描程序

{P2=0xfe; 先选定第一行

  temp=P2;

  temp=temp&0xf8;  //列线全为1,行线为0

 while(temp!=0xf8)

  {delay(15); 延时去抖

   temp=P2;

   temp=temp&0xf8;

   while(temp!=0xf8)

  { temp=P2;

   switch(temp) 判断哪列按下

   {case 0xf6:num=0;flag=1;break;//第一列按下

    case 0xee:num=1;flag=1 ;break;//第二列按下

    case 0xde:num=2;flag=1;break;//第三列按下

   }

    while(temp!=0xf8)

    {temp=P2;

    temp=temp&0xf8;

   }

     }

    }

   P2=0xfd; 选定第二行,列线为1

   temp=P2;

   temp=temp&0xf8;

   while(temp!=0xf8)

   { delay(15);

     temp=P2;

     temp=temp&0xf8;

     while(temp!=0xf8)

    {temp=P2;

      switch(temp) //判断哪列按下

     {case 0xf5:num=3;flag=1;//第一列按下

     break;

     case 0xed:num=4;flag=1;//第二列按下

     break;

     case 0xdd:num=5;flag=1;//第三列按下

     break;

     }

     while(temp!=0xf8)

      {temp=P2;

       temp=temp&0xf8;

      }

   }

   }

   P2=0xfb;//选定第三行

   temp=P2;

   temp=temp&0xf8;

   while(temp!=0xf8)

    {

     delay(15);

     temp=P2;

     temp=temp&0xf8;

     while(temp!=0xf8)

     {temp=P2;

     switch(temp)

   {  case 0xf3:num=6;flag=1;break;

   case 0xeb:num=7;flag=1;break;

   case 0xdb:num=8;flag=1;break;

  }

  while(temp!=0xf8)

    {  temp=P2;

   temp=temp&0xf8;

    }

  }

 }return(num);   

}

   void main()

 {  uchar m=0,w=0;

   init(); //LCD初始化

 w第一行显示 

  for(r=0;r<15;r++)

 {write_data(table1[r]);

  delay(5);

 }

write_com(0x80+0x40);//第二行显示

for(r=0;r<15;r++)

 {write_data(table2[r]);

   delay(5);

 }

 write_com(0x0c); 

 do

 {keyscan();}

  while(num!=8); //等待开锁键按下

  mima(); 密码输入处理函数

while((pswd[m]==init_pswd[m])&m<6)//密码比较

{ m++;}

if(m>=6)//密码正确

{ P1_3=0; //开锁指示灯亮

 keyscan();

 //是否修改密码

 mima1(); 修改密码函数

}

else//密码有误

 { m=0;

  write_com(0x80+0x40);//显示第二行

  for(r=0;r<14;r++)

   {delay(20);

   write_data(table4[r]);

   }

  ;

  init();

  for(r=0;r<16;r++)

   {delay(20);

   write_data(table6[r]);

   }

  delay(2000);

   //密码输入处理函数

  while((pswd[m]==init_pswd[m])&m<6)//再次比较

   {m++;}

  if(m>=6)

   {  P1_3=0; 

    mima1();//修改密码函数

   }

  else

  { m=0;

   write_com(0x80+0x40);

   for(r=0;r<14;r++)

   {delay(20);

    write_data(table4[r]);

   }delay(2000);

     init();

    for(r=0;r<14;r++)

   delay(20);

     write_data(table7[r]);

    }delay(2000);

   mima();

  while((pswd[m]==init_pswd[m])&m<6)//第三次比较

     {m++; }

     if(m>=6)

      {P1_3=0;//密码正确,则开锁指示灯亮

      mima1();//密码修改函数

      }

     else

     { init();

      write_com(0x80+0x40);

      for(r=0;r<13;r++)

      {delay(20);

      write_data(table9[r]); 

      }

     write_com(0x0c);     

        while(1)

       { P1_5=~P1_5;//报警指示灯闪烁

       delay(30);

        Alarm(90);

        Alarm(120); //产生“滴滴”声 

       }

     }   

   }

  } 

}

void mima()  //密码输入程序

{ uchar w=0;

  init();

  for(r=0;r<9;r++)

   {delay(20);

   write_data(table10[r]);

   }

 do

   {flag=0;

  write_com(0x80+9+w);

  if(flag==1&&num<=5)

   {  pswd[w]=num;

     write_data(table3[w]);

     w++;  //输入密码

   if(w==6)

  

   }

if(flag==1&&num==7) //删除误输入的密码,即返回上一步.

   { w--; 删除密码

    if(w==255) //删除完密码

     w=w+1;

    write_com(0x80+9+w);

    write_data(table11[w+1]);

    if(flag==1&&num<=5)

     {pswd[w]=num;

      write_data(table3[w]);    

    }

    }

  while(w<=5);

}

/***************************************************

 输入初始密码正确后,密码修改

***************************************************/

void  mima1()

{  uchar f=0,n=0,d=0;

  write_com(0x80+0x40);

   for(r=0;r<14;r++)

   {   delay(20);

   write_data(table5[r]);

   }

   delay(2000);

     do

     {   num=9;//按键不显示,锁住按键

      keyscan();

     }while(num!=6);   

  if(flag==1&&num==6)

 { init(); P1_3=1; P1_4=0;

  for(r=0;r<15;r++)

  { delay(20);

   write_data(table8[r]);

   }

 write_com(0x0c);

  write_com(0x80+0x40+n);

 write_com(0x0e);

  }

//////////////////////////第一次输入修改密码////////////////////////////////

  do{ num=9;//按键不显示,锁住按键

   keyscan();

   write_com(0x80+0x40+n);      if(flag==1&&num<=5)

    {  init_pswd[n]=num;

     write_data(table3[n]);

     n++;

   if(n==6)

   }

if(flag==1&&num==7) //删除误输入的密码,即返回上一步.

 { n--;

 if(n==255)

 n=n+1;

write_com(0x80+0x40+n);      

write_data(table11[n]);        if(flag==1&&num<=5)//显示0-5键值

 { pswd[n]=num;          write_data(table3[n]);   

 }

 }     

}while(n<=5);

//////////////////////////////////////////////////////////////////////////////////

第二次输入修改密码,并判断是否正确

////////////////////////////////////////////////////////////////////////////////////

 init();

 for(r=0;r<12;r++)

   {delay(20);

  write_data(table13[r]); }

 do

  {  flag=0;//锁住按键

   keyscan();

  write_com(0x80+0x40+d);

  if(flag==1&&num<=5)

   {  pswd[d]=num;

     write_data(table3[d]);

     d++;

    if(d==6)

   write_com(0x0c);

   }

if(flag==1&&num==7) //删除误输入的密码,即返回上一步.

  {  d--;

    if(d==255)

    d=d+1;

write_com(0x80+0x40+d);   

write_data(table11[d+1]);

 if(flag==1&&num<=5)

  { pswd[d]=num;         write_data(table3[d]);   

   }  }

  while(d<=5);

 while((pswd[f]==init_pswd[f])&f<6)//比较密码是否正确

    {f++;}

 if(f>=6)//密码正确

  {  init();

   for(r=0;r<15;r++)

   {  delay(20); 

    write_data(table12[r]);

    }delay(5000);

     P1_4=1;//修改密码指示灯灭

    main(); 

   }else

   {  init();

    for(r=0;r<15;r++)

    {  delay(20);

      write_data(table14[r]);

    }delay(1000);

      main(); //返回主界面    

 }

  void Alarm(uchar t) //报警函数,产生“滴滴”声

{  uchar k,j;

 for(k=0;k<250;k++)

 { P2_7=~P2_7;

  for(j=0;j}下载本文

显示全文
专题