基于51单片机密码锁课程设计报告

更新时间:2023-10-27 18:57:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

一.设计目的

在日常的生活和工作中,住宅与部门的安全防范、单位的文件档案、财务报表以及一些个人资料的保存多以加锁的办法来解决。若使用传统的机械式钥匙开锁,人们常需要携带多把钥匙,使用极不方便,且钥匙丢失后安全性即大打折扣。随着科学技术的不断发展,人们对日常生活中的安全保险器件的要求越来越高。为了满足人们对锁的使用要求,增加其安全性,用密码代替钥匙的密码锁应运而生。密码锁具有安全性高、成本低、功耗低、易操作等优点。

在安全技术防范领域,具有防盗报警功能的电子密码锁逐渐代替传统的机械式密码锁,克服了机械式密码锁密码量少,安全性能差的缺点,使密码锁无论在技术上还是在性能上都大大提高一步。随着大规模集成电路技术的发展,特别是单片机的问世,出现了带微处理器的只能密码锁,它除了具有电子密码锁的功能外,还引入了智能化管理、专家分析系统等功能,从而使密码锁具有很高的安全性、可靠性,应用日益广泛。

本设计采用单片机为主控芯片,结合外围电路,组成电子密码锁,用户想要打开锁,必先通过提供的键盘输入正确的密码才能将锁打开,密码输入错误就有提示,为了提高安全性,当密码输入错误次将报警。密码可以由用户自己修改设定,锁开后才能修改密码。修改密码前必须再次输入密码,在输入新密码时候需要二次确认,以防止误操作。

二.设计要求和方案选择

1、方案:用AT89C52设计的多功能密码锁。以单片机作为微控制器,可以实现基于以上优点,按键有效指示、输入错误、控制开锁、错误报警、密码修改等功能,工作稳定可靠,保密性高,实用性强。 2、电子密码锁总体设计

电源输入 键盘输入

复位电路 显示电路

AT89C52

密码存储 报警电路

晶振电路 开锁电路

三.硬件部分

AT89C52简介:

单片机AT89C52简介

AT89C52是美国ATMEL公司生产的低电压,高性能CMOS 8位单片机,片内含4K bytes的可反复擦写的只读程序存储器(EPROM)和128bytes的随机存取数据序存器(RAM),器件采用ATMEL公司的高密度/非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器(CPU)和FLASH存储单元,AT89C52单片机为许多嵌入式控制系统提供了一种灵活行高且价廉的方案。 主要特性:

? 与MCS-51 兼容

? 4K字节可编程FLASH存储器(寿命:1000写/ 擦循环)

? 全静态工作:0Hz-24KHz ? 三级程序存储器保密锁定 ? 128*8位内部RAM ? 32条可编程I/O线

? 两个16位定时器/计数器 ? 5个中断源 AT89C52 ? 可编程串行通道

? 低功耗的闲置和掉电模式 ? 片内振荡器和时钟电路

1. 总电路图

2. 键盘电路

按键与家庭电话式的按键方式

3. 复位电路

4. 晶振电路

5. 显示电路

显示容量 芯片工作电压 工作电流 16*2个字符 4.5~5.5V 2.0mA(5v) 时刻显示输入输出的内容以及操作过程。 6. 报警电路

字符尺寸 3.95*4.35mm

当输入密码错误次数大于等于3次时,会发出声响报警。 7. 开锁电路

Send(0xa0); Ack();

Send(Address+i); Ack();

Send(*(PData+i)); Ack(); Stop(); mDelay(20); } }

voidRdFromROM(uchar Data[],ucharAddress,ucharNum) {

uchari;

uchar *PData; PData=Data;

for(i=0;i

Start(); Send(0xa0); Ack();

Send(Address+i); Ack(); Start(); Send(0xa1); Ack();

*(PData+i)=Read(); Scl=0; NoAck(); Stop(); } }

//=======================================LCD1602=============================

#define yi 0x80

//LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80) #define er 0x80+0x40

//LCD第二行初始位置(因为第二行第一个字符位置地址是0x40) //----------------延时函数,后面经常调用---------------------- void delay(uintxms)//延时函数,有参函数 {

uintx,y;

for(x=xms;x>0;x--) for(y=110;y>0;y--); }

//--------------------------写指令--------------------------- write_1602com(uchar com)//****液晶写入指令函数**** {

lcd1602_rs=0;//数据/指令选择置为指令 ...... lcd1602_rw=0; //读写选择置为写 P0=com;//送入数据 delay(1);

lcd1602_en=1;//拉高使能端,为制造有效的下降沿做准备 delay(1);

lcd1602_en=0;//en由高变低,产生下降沿,液晶执行命令 }

//-------------------------写数据----------------------------- write_1602dat(uchardat)//***液晶写入数据函数**** {

lcd1602_rs=1;//数据/指令选择置为数据 lcd1602_rw=0; //读写选择置为写 P0=dat;//送入数据 delay(1);

lcd1602_en=1; //en置高电平,为制造下降沿做准备 delay(1);

lcd1602_en=0; //en由高变低,产生下降沿,液晶执行命令 }

//-------------------------初始化------------------------- voidlcd_init(void) {

write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据

write_1602com(0x0c);//开显示不显示光标

write_1602com(0x06);//整屏不移动,光标自动右移 write_1602com(0x01);//清显示 }

//==============将按键值编码为数值========================= unsigned char coding(unsigned char m) {

unsigned char k; switch(m) {

case (0x18): k=1;break; case (0x28): k=2;break; case (0x48): k=3;break; case (0x88): k='A';break; case (0x14): k=4;break; case (0x24): k=5;break; case (0x44): k=6;break;

case (0x84): k='B';break; case (0x12): k=7;break; case (0x22): k=8;break; case (0x42): k=9;break; case (0x82): k='C';break; case (0x11): k='*';break; case (0x21): k=0;break; case (0x41): k='#';break; case (0x81): k='D';break; }

return(k); }

//=====================按键检测并返=============================== unsigned char keynum(void) {

unsigned char row,col,i; P1=0xf0;

if((P1&0xf0)!=0xf0) {

Delay5Ms(); Delay5Ms();

if((P1&0xf0)!=0xf0) {

row=P1^0xf0; //确定行线 i=0;

P1=a[i]; //精确定位 while(i<4) {

if((P1&0xf0)!=0xf0) {

col=~(P1&0xff); //确定列线

break; //已定位后提前退出 } else {

i++; P1=a[i]; } } } else {

return 0;

按键值

回 }

while((P1&0xf0)!=0xf0); return (row|col); //行线与列线组合后返回 }

else return 0; //无键按下时返回0 }

//=======================一声提示音,表示有效输入======================== voidOneAlam(void) {

ALAM=0;

Delay5Ms(); ALAM=1; }

//========================二声提示音,表示操作成功======================== voidTwoAlam(void) {

ALAM=0;

Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0;

Delay5Ms(); ALAM=1; }

//========================三声提示音,表示错误======================== voidThreeAlam(void) {

ALAM=0;

Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0;

Delay5Ms(); ALAM=1; Delay5Ms(); ALAM=0;

Delay5Ms(); ALAM=1; }

//=====================显示输入的N个数字,用H代替以便隐藏============================

voidDisplayOne(void) {

// DisplayOneChar(9+N,1,'*'); write_1602com(yi+5+N); write_1602dat('*'); }

//=======================显示提示输入========================= voidDisplayChar(void) {

unsigned char i; if(pass==1) {

//DisplayListChar(0,1,LockOpen); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(LockOpen[i]); } } else {

if(N==0) {

//DisplayListChar(0,1,Error); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Error[i]); } } else {

//DisplayListChar(0,1,start_line); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(start_line[i]); } } } }

voidDisplayInput(void) {

unsigned char i;

if(CorrectCont==1) {

//DisplayListChar(0,0,Input); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Input[i]); } } }

//========================重置密码==================================================

//==================================================================================

voidResetPassword(void) {

unsigned char i; unsigned char j; if(pass==0) {

pass=0;

DisplayChar(); ThreeAlam(); } else {

if(ReInputEn==1) {

if(N==6) {

ReInputCont++; if(ReInputCont==2) {

for(i=0;i<6;) {

if(TempPassword[i]==InputData[i]) //将两次输入的新密码作对比

i++; else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); //错误提示 pass=0;

ReInputEn=0; //关闭重置功能, ReInputCont=0; DisplayChar(); break; } }

if(i==6) {

//DisplayListChar(0,1,ResetOK); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(ResetOK[j]); }

TwoAlam(); //操作成功提示

WrToROM(TempPassword,0,6); //将新密码写入24C02存储

ReInputEn=0; }

ReInputCont=0; CorrectCont=0; } else {

OneAlam();

//DisplayListChar(0, 1, again); //显示再次输入一次

write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(again[j]); } for(i=0;i<6;i++) {

TempPassword[i]=InputData[i];//将第一次输入的数据暂存起来

} }

N=0; //输入数据位数计数器清零

} } } }

//=======================输入密码错误超过三过,报警并锁死键盘====================== voidAlam_KeyUnable(void) {

P1=0x00; {

ALAM=~ALAM; Delay5Ms(); } }

//=======================取消所============================================ void Cancel(void) {

unsigned char i; unsigned char j;

//DisplayListChar(0, 1, start_line); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(start_line[j]); }

TwoAlam(); //提示音 for(i=0;i<6;i++) {

InputData[i]=0; }

KEY=1; //关闭锁 ALAM=1; //报警关

operation=0; //操作标志位清零 pass=0; //密码正确标志清零 ReInputEn=0; //重置输入充许标志清零 ErrorCont=0; //密码错误输入次数清零 CorrectCont=0; //密码正确输入次数清零 ReInputCont=0; //重置密码输入次数清零 open_led=1; s3_keydown=0;

有操作 key_disable=0;

N=0; //输入位数计数器清零 }

//==========================确认键,并通过相应标志位执行相应功能=============================== void Ensure(void) {

unsigned char i,j;

RdFromROM(CurrentPassword,0,6); //从24C02里读出存储密码 if(N==6) {

if(ReInputEn==0) //重置密码功能未开启 {

for(i=0;i<6;)

{

if(CurrentPassword[i]==InputData[i]) {

i++; } else

{

ErrorCont++;

if(ErrorCont==3) //错误输入计数达三次时,报警并锁定键盘

{

write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Error[i]); } do

Alam_KeyUnable(); while(1); } else {

TR0=1; //开启定时 key_disable=1; //锁定键盘 pass=0; break; } } }

if(i==6)

{

CorrectCont++;

if(CorrectCont==1) //正确输入计数,当只有一次正确输入时,开锁, {

//DisplayListChar(0,1,LockOpen); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(LockOpen[j]); }

TwoAlam(); //操作成功提示音 KEY=0; //开锁

pass=1; //置正确标志位 TR0=1; //开启定时

open_led=0; //开锁指示灯亮 for(j=0;j<6;j++) //将输入清除 {

InputData[i]=0; } }

else //当两次正确输入时,开启重置密码功能

{

//DisplayListChar(0,1,SetNew); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(SetNew[j]); }

TwoAlam(); //操作成功提示

ReInputEn=1; //允许重置密码输入 CorrectCont=0; //正确计数器清零 } }

else

//=========================当第一次使用或忘记密码时可以用131420对其密码初始化============ {

if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&&(InputData[5]==0)) {

WrToROM(initpassword,0,6); //强制将初始密码写入24C02存储

//DisplayListChar(0,1,initword); //显示初始化密码

write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(initword[j]); }

TwoAlam(); Delay400Ms(); TwoAlam(); N=0; } else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); //错误提示音 pass=0; } } }

else //当已经开启重置密码功能时,而按下开锁键, {

//DisplayListChar(0,1,Er_try); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Er_try[j]); }

ThreeAlam(); } } else {

//DisplayListChar(0,1,Error); write_1602com(er); for(j=0;j<16;j++) {

write_1602dat(Error[j]); }

ThreeAlam(); //错误提示音 pass=0; }

N=0; //将输入数据计数器清零,为下一次输入作准备

operation=1; }

//==============================主函数=============================== void main(void) {

unsigned char KEY2,NUM,M; unsigned char i,j; P1=0xFF; TMOD=0x11; TL0=0xB0; TH0=0x3C; EA=1; ET0=1; TR0=0;

Delay400Ms(); //启动等待,等LCM讲入工作状态 lcd_init(); //LCD初始化

write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示 for(i=0;i<16;i++) {

write_1602dat(name[i]);//向液晶屏写日历显示的固定符号部分 }

write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示

for(i=0;i<16;i++) {

write_1602dat(start_line[i]);//写显示时间固定符号,两个冒号 }

write_1602com(er+9); //设置光标位置 write_1602com(0x0f); //设置光标为闪烁 Delay5Ms(); //延时片刻(可不要)

N=0; //初始化数据输入位数 while(1) {

if(key_disable==1) Alam_KeyUnable();

else

ALAM=1; //关报警

KEY2=keynum(); if(KEY2!=0) {

if(key_disable==1) {

second=0; } else {

NUM=coding(KEY2); {

switch(NUM) {

case ('A'): ; break; case ('B'): ; break; case ('C'): ; break;

case ('D'): ResetPassword(); break; //重新设置密码

case ('*'): Cancel(); break; //取消当前输入

case ('#'): Ensure(); break; 确认键,

default: {

//DisplayListChar(0,1,Input); write_1602com(er); for(i=0;i<16;i++) {

write_1602dat(Input[i]); }

operation=0;

if(N<6) //当输入的密码少于6位时,接受输入并保存,大于6位时则无效。 {

OneAlam(); //按键提示音

//DisplayOneChar(6+N,1,'*'); for(j=0;j<=N;j++) {

write_1602com(er+6+j); write_1602dat(b[NUM]);

// Delay5Ms(); Delay5Ms();

write_1602com(er+6+j); write_1602dat('*'); }

InputData[N]=NUM; N++; }

else //输入数据位数大于6后,忽略输入 {

OneAlam();

for(j=0;j<=N;j++) {

write_1602com(er+6+j); write_1602dat('*'); } N=6; break; } } } } } } } }

//*********************************中断服************************************** void time0_int(void) interrupt 1 {

TL0=0xB0; TH0=0x3C; //TR0=1; countt0++;

if(countt0==20) {

countt0=0; second++; if(pass==1) {

if(second==1) {

务函数

}

}

open_led=1; TR0=0; TL0=0xB0; TH0=0x3C; second=0; } } else {

if(second==3) {

TR0=0; second=0;

key_disable=0; s3_keydown=0; TL0=0xB0; TH0=0x3C; } else

TR0=1; }

//关指示灯 //关定时器

五.调试及运行结果

1、使用keil生成hex文件

2、使用proteus仿真

使用proteus绘制原理图并将keil生成的hex程序文件载入到单片机中。

本文来源:https://www.bwwdw.com/article/n3l2.html

Top