目录
第一章 绪论
摘要:随着科学技术的不断发展,人们在日常生活与工作中对保险器件的要求越来越高。同时,电子设备也正在向智能化与微型化不断发展,电子密码控制系统已经越来越符合人们的要求。而单片机已经成为电子产品研制和开发中首选的控制器。为了满足人们对锁的使用要求,增加其安全性,同时克服传统锁具带来的不方便性,用数据密码代替钥匙的智能密码锁便应运而生。智能密码锁具有安全性商、操作简易、成本低、功耗低等优点。
本次设计由单片机系统、矩阵键盘、LCD显示和报警系统组成。系统能完成开锁、报警、修改用户密码等基本的密码锁功能。除上述基本的密码锁功能外,依据实际的情况还可以添加遥控功能。所采用的编程语言是C语言。本系统电路稳定性高、成木低廉、功能实用,符合办公室、住宅等场所的用锁要求,具有推广价值。
第二章 系统论述
2.1 总体方案
以单片机AT89C51为核心设计一款电子密码锁,该密码锁可以输入六位密码来验证开锁操作,此外还实现了灯光警示作用,可以让使用者更加直观地发现是否开锁,其次在LCD1602上显示一系列操作提示,让本设计更具有可操作性。
根据系统的设计要求,用矩阵键盘来实现字符的输入,用LCD1602作为显示模块显示密码以及提示操作字符,此外采用开关模拟开关锁,LCD灯作为开锁或者密码模式的提示。
该系统的总体设计思路如下:本设计的主要难点在于矩阵键盘和LCD1602的设计与配合,要通过矩阵键盘来键入字符从而显示在LCD1602显示屏上,并且通过运算来验证密码的正确性或者进行其他的系统操作如清空显示,确认或者进入密码修改模式。其中矩阵键盘通过循环扫描方式,用八位P1口来实现16位按键操作。而密码验证则需用到<string.h>库中的比较字符串函数“strcmp”,此外通过一些列的数组运算来保存旧密码赋值新密码等操作。
2.2 设计目标
1.单片机最小系统;
2.LCD1602用于显示模块,让输入的密码直观可见;
3.矩阵键盘,用于输入输入密码,反映输入字符;
4.LED灯,用于提示密码锁的状态,让设计更可观,也可用作检验程序;
5.开关,用于模拟执行元件,反映开关锁状态。
图 1-硬件选用以及电路连接
第三章 系统硬件的设计
3.1单片机最小系统的设计
3.1.1 AT89C51
AT89C51是一种带4K字节闪烁可编程可擦出只读存储器的低电压,高性能 CMOS8位微处理器,俗称单片机。该器件采用ATMEL高密度非易失存储器制造技术,与工业标准MCS-51指令集合输出管脚相兼容。由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的AT89C51是一种高效微控制器,为很多嵌入式控制系统提供了一种灵活性高且廉价的方案。
3.1.2 晶振电路和复位电路
复位电路和晶振电路是维持单片机最小系统运行的基本模块。复位电路采用手动复位方式,晶振电路选取12.0M无源晶振接入XTAL1和XTAL2引脚,并联2个30pF陶瓷电容帮助起振。
图 2-晶振和复位电路
3.2显示模块
使用的是LCD1602显示屏作为显示模块,其中有两行十六位用于显示字符,很满足密码锁的显示要求,可以进行操作提示以及输入字符,其中初始化LCD1602的子程序中注释了该如何使用本模块达到本次设计要求。(关于LCD1602模块读者可参考http://t.csdnimg.cn/w417a)
图 3-Lcd1602显示模块
3.3矩阵键盘
使用八位P1口,采用循环扫描的方式来确认按钮是否按下,对P1的低四位进行循环取低电平,例如让P1.3置为低电平,若EMPTY按下则P1.4也被置为低电平,此时表示EMPT被按下。
图 4-矩阵键盘
3.4警示灯及模拟锁
进入密码修改模式将P3.5置为低电平,密码正确将P3.6置为低电平,P3.7若置为低电平则将P3.6重新置为高电平。
图 5-警示灯及模拟锁
第四章 系统软件的设计
4.1设计流程
子函数环节(用于主函数反复调用,让程序的可维护性提升):
图 6-子函数设计流程图
子函数列表:
主函数环节:
1.正常模式下开锁流程图
图 7-正常模式开锁流程图
2.修改密码模式下流程图
图 8-修改密码模式流程图
进入修改密码模式时,创建一个数组用于将原密码保存,作为退出该模式的依据;创建另一个数组存放修改操作时送人的密码,数值输入完成后再送入存放密码的数组,避免提前退出模式。
uchar Old_password[7];
uchar New_password[7];
uchar i;
for(i=0;i<6;i++) Old_password[i]=password[i];
while(strcmp(Old_password,password)==0)
{
限定位数时,让count=6时进入循环,重新定义矩阵键盘的扫描方式,只扫描功能键所在位置。
//*********************限定位数*********************//
while(count==6){
P1=0xF7;
if(P1!=0xF7){
DelayMs(10);
if(P1!=0xF7){
switch(P1){
case 0xE7:
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
break;
case 0xB7:
while(P1!=0xF7);
if(strcmp(str,password)==0){
Status1=0;
LcdWriteCmd(0x01);
LcdShowCorrect();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
}
else if(strcmp(str,"###***")==0){
Status0=0;
LcdWriteCmd(0x01);
LcdModifing();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) str[i]='\0';
count=0;
Modifing();
Status0=1;
}
}
}
}
}
第五章 系统仿真与调试
5.1硬件搭建
如 图 1-硬件选用以及电路连接 所示硬件选用以及电路连接。
选用元件如下:
AT89C51、BUTTON、CAP、CAP-PAL、CRYSTAL、LED-RED、LED-YELLOW、LM016L、RESPACK-8、RES、SWITCH.
5.2模拟仿真
完整仿真演示视频已上传至该地址:Proteus——基于51单片机的电子密码锁设计仿真_哔哩哔哩_bilibili
源程序代码
#include <reg51.h>
#include <string.h>
#define uchar unsigned char
#define uint unsigned int
sbit LcdRs_P = P2^5;
sbit LcdRw_P = P2^6;
sbit LcdEn_P = P2^7;
sbit Status0 = P3^5;
sbit Status1 = P3^6;
sbit Lock = P3^7;
uchar count=0;
uchar str[7];
uchar password[7]={'1','2','3','4','5','6'};
//*********************子函数区*********************//
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}
void LcdWriteCmd(uchar cmd)
{
LcdRs_P = 0; //选择写指令
LcdRw_P = 0; //选择写
LcdEn_P = 0; //E使能拉低
P0=cmd; //把指令送入P0
DelayMs(2); //延时一小会儿,让1602准备接收数据
LcdEn_P = 1; //使能线电平变化上升沿,命令送入1602的8位数据口
DelayMs(2);//延时,让数据发送
LcdEn_P = 0; //使能线拉低
}
void LcdWriteData(uchar dat)
{
LcdRs_P = 1; //选择写数据
LcdRw_P = 0; //选择写
LcdEn_P = 0; //E使能拉低
P0=dat; //把数据送入P0
DelayMs(2); //延时一小会儿,让1602准备接收数据
LcdEn_P = 1; //使能线电平变化上升沿,命令送入1602的8位数据口
DelayMs(2);//延时,让数据发送
LcdEn_P = 0;//使能线拉低
}
void LcdInit()
{
LcdWriteCmd(0x38); // 16*2显示,5*7点阵,8位数据口 0011 1000
LcdWriteCmd(0x0F); // 开显示,显示光标闪烁 0000 1111
LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移 0000 0110
LcdWriteCmd(0x01); // 清屏
}
void LcdGotoXY(uchar line,uchar column)
{
if(line==0)
LcdWriteCmd(0x80+column);
if(line==1)
LcdWriteCmd(0x80+0x40+column);
}
void LcdPrintStr(uchar *str)
{
while(*str!='\0')
LcdWriteData(*str++);
}
void LcdShowInit()
{
LcdGotoXY(0,0);
LcdPrintStr("Enter Password:");
LcdGotoXY(1,0);
}
void LcdShowInit0()
{
LcdGotoXY(0,0);
LcdPrintStr("New Password:");
LcdGotoXY(1,0);
}
void LcdShowCorrect()
{
LcdGotoXY(0,0);
LcdPrintStr("====Password====");
LcdGotoXY(1,0);
LcdPrintStr("====Correct====");
}
void LcdShowError()
{
LcdGotoXY(0,0);
LcdPrintStr("====Password====");
LcdGotoXY(1,0);
LcdPrintStr("=====Error=====");
}
void LcdModifing()
{
LcdGotoXY(0,0);
LcdPrintStr("====Password====");
LcdGotoXY(1,0);
LcdPrintStr("====Modifing====");
}
void LcdModified()
{
LcdGotoXY(0,0);
LcdPrintStr("==Password has==");
LcdGotoXY(1,0);
LcdPrintStr("==been modified=");
}
void LcdRetype()
{
LcdGotoXY(0,0);
LcdPrintStr("===Please retype");
LcdGotoXY(1,0);
LcdPrintStr("Six-digit number");
}
//*********************修改密码*********************//
void Modifing()
{
uchar Old_password[7];
uchar New_password[7];
uchar i;
for(i=0;i<6;i++) Old_password[i]=password[i];
while(strcmp(Old_password,password)==0)
{
P1=0xFE;
if(P1!=0xFE){
DelayMs(10);
if(P1!=0xFE){
switch(P1){
case 0xEE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("1");
New_password[count]='1';
count++;
break;
case 0xDE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("2");
New_password[count]='2';
count++;
break;
case 0xBE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("3");
New_password[count]='3';
count++;
break;
case 0x7E:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("4");
New_password[count]='4';
count++;
break;
}
}
}
P1=0xFD;
if(P1!=0xFD){
DelayMs(10);
if(P1!=0xFD){
switch(P1){
case 0xED:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("5");
New_password[count]='5';
count++;
break;
case 0xDD:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("6");
New_password[count]='6';
count++;
break;
case 0xBD:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("7");
New_password[count]='7';
count++;
break;
case 0x7D:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("8");
New_password[count]='8';
count++;
break;
}
}
}
P1=0xFB;
if(P1!=0xFB){
DelayMs(10);
if(P1!=0xFB){
switch(P1){
case 0xEB:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("9");
New_password[count]='9';
count++;
break;
case 0xDB:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("0");
New_password[count]='0';
count++;
break;
}
}
}
//*********************功能键区*********************//
P1=0xF7;
if(P1!=0xF7){
DelayMs(10);
if(P1!=0xF7){
switch(P1){
case 0xE7: //清空
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) New_password[i]='\0';
count=0;
break;
case 0xB7: //输入
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdRetype();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) New_password[i]='\0';
count=0;
break;
}
}
}
//*********************限定位数*********************//
while(count==6){
P1=0xF7;
if(P1!=0xF7){
DelayMs(10);
if(P1!=0xF7){
switch(P1){
case 0xE7:
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) New_password[i]='\0';
count=0;
break;
case 0xB7:
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdModified();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) password[i]=New_password[i];
for(i=0;i<count;i++) New_password[i]='\0';
count=0;
Status0=1;
}
}
}
}
}
}
//*********************主函数区*********************//
void main()
{
uchar i;
LcdInit();
LcdShowInit();
while(1)
{
//*********************字符键区*********************//
P1=0xFE;
if(P1!=0xFE){
DelayMs(10);
if(P1!=0xFE){
switch(P1){
case 0xEE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("1");
str[count]='1';
count++;
break;
case 0xDE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("2");
str[count]='2';
count++;
break;
case 0xBE:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("3");
str[count]='3';
count++;
break;
case 0x7E:
while(P1!=0xFE);
LcdGotoXY(1,count);
LcdPrintStr("4");
str[count]='4';
count++;
break;
}
}
}
P1=0xFD;
if(P1!=0xFD){
DelayMs(10);
if(P1!=0xFD){
switch(P1){
case 0xED:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("5");
str[count]='5';
count++;
break;
case 0xDD:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("6");
str[count]='6';
count++;
break;
case 0xBD:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("7");
str[count]='7';
count++;
break;
case 0x7D:
while(P1!=0xFD);
LcdGotoXY(1,count);
LcdPrintStr("8");
str[count]='8';
count++;
break;
}
}
}
P1=0xFB;
if(P1!=0xFB){
DelayMs(10);
if(P1!=0xFB){
switch(P1){
case 0xEB:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("9");
str[count]='9';
count++;
break;
case 0xDB:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("0");
str[count]='0';
count++;
break;
case 0xBB:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("#");
str[count]='#';
count++;
break;
case 0x7B:
while(P1!=0xFB);
LcdGotoXY(1,count);
LcdPrintStr("*");
str[count]='*';
count++;
break;
}
}
}
//*********************功能键区*********************//
P1=0xF7;
if(P1!=0xF7){
DelayMs(10);
if(P1!=0xF7){
switch(P1){
case 0xE7: //清空
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
break;
case 0xB7: //输入
while(P1!=0xF7);
if(strcmp(str,password)==0){ //验证密码
Status1=0;
LcdWriteCmd(0x01);
LcdShowCorrect();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
}
else if(strcmp(str,"###***")==0){ //修改密码
Status0=0;
LcdWriteCmd(0x01);
LcdModifing();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) str[i]='\0';
count=0;
Modifing();
Status0=1; //修改密码退出提示
}
//**************************************************//
else{
LcdWriteCmd(0x01);
LcdShowError();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit();
count=0;
break;
}
}
}
}
//*********************限定位数*********************//
while(count==6){
P1=0xF7;
if(P1!=0xF7){
DelayMs(10);
if(P1!=0xF7){
switch(P1){
case 0xE7:
while(P1!=0xF7);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
break;
case 0xB7:
while(P1!=0xF7);
if(strcmp(str,password)==0){
Status1=0;
LcdWriteCmd(0x01);
LcdShowCorrect();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit();
for(i=0;i<count;i++) str[i]='\0';
count=0;
}
else if(strcmp(str,"###***")==0){
Status0=0;
LcdWriteCmd(0x01);
LcdModifing();
DelayMs(2000);
LcdWriteCmd(0x01);
LcdShowInit0();
for(i=0;i<count;i++) str[i]='\0';
count=0;
Modifing();
Status0=1;
}
}
}
}
}
if(Lock==0) Status1=1;
}
}