51单片机课程设计 电子密码锁 - 图文

更新时间:2024-06-21 13:03:01 阅读量: 综合文库 文档下载

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

华中师范大学武汉传媒学院 传媒技术学院 电子信息工程2011 仅发布百度文库,版权所有.

基于单片机的密码锁的设计

1设计题目:电子密码锁

要求 采用AT89S51单片机为主控芯片,通过软件程序组成电子密码锁系统 2设计框图

键盘输入模块 复位电路 密码存储模块

AT89S51 开锁电路 报警电路 显示模块 3方案设计

课题设计目标

本设计采用AT89S51单片机为主控芯片,通过软件程序组成电子密码锁系统,能够实现:

1. 正确输入密码前提下,开锁提示; 2. 错误输入密码情况下,蜂鸣器报警; 3. 密码可以根据用户需要更改; 4. 断电存储功能 主控部分的选择

选用单片机作为系统的核心部件,实现控制与处理的功能。单片机具有资源丰富、速度快、编程容易等优点。利用单片机内部的随机存储器(RAM)和只读存储器(ROM)及其引脚资源,外接液晶显示(LCD),键盘输入等实现数据的处理传输和显示功能,基本上能实现设计指标。 密码输入方式的选择

由各按键组成的矩阵键盘每条行线和列线都对应一条I/O口线,键位设在行线和列线的交叉点,当一个键按下就会有某一条行线与某一条列线接触,只要确定

接触的是哪两条线,即哪两个I/O口线,就可以确定哪一个键被触动。行线设计成上拉口线,初始时被置高电位,列线悬空,初始置低。通过不断读行线口线,或者中断方式触发键位扫描。当发现有键按下,将列线逐一置低,其他列线置高,读行线口线。当某条列线置低时,某条行线也被拉低,则确定这两条线的交点处的按钮被按下。每个按键都可通过程序赋予功能,从而完成密码识别。

4 硬件原图设计

5程序流程图

初始化

开锁

密码正确 开始 修改 输入旧密码 N Y N N 开锁 出错报警

主程序流程图

返回 原密码相同 Y 设新密码 键功能程序流程图

键功能程序 N Y 确认程序 N 键值=设置? Y 设置程序 N Y 开锁程序 键值=0~9? Y 密码输入程序 键值=开锁? 键值=确认?

N 返回

开锁程序流程图

输入密码

输入密码正

Y 返回 开锁成功 确? N 报警程序 确认程序 按开锁键 LCD初始化 开锁

6仿真图

7制作

本设计主要由单片机、矩阵键盘、液晶显示器和密码存储等部分组成。其中矩阵键盘用于输入数字密码和进行各种功能的实现。由用户通过连接单片机的矩阵键盘输入密码,后经过单片机对用户输入的密码与自己保存的密码进行对比,从而判断密码是否正确,然后控制引脚的高低电平传到开锁电路或者报警电路控制开锁还是报警,实际使用时只要将单片机的负载由继电器换成电子密码锁的电磁铁吸合线圈即可,当然也可以用继电器的常开触点去控制电磁铁吸合线圈。本系统共有两部分构成,即硬件部分与软件部分。其中硬件部分由电源输入部分、键盘输入部分、密码存储部分、显示部分、报警部分组成,软件部分对应的由主程序、初始化程序、LCD显示程序、键盘扫描程序、启动程序、关闭程序、键功能程序、密码设置程序、EEPROM读写程序和延时程序等组成。

8调试

密码锁主控制部分电源需要用5V直流电源供电,把频率为50Hz、有效值为220V的单相交流电压转换为幅值稳定的5V直流电压。其主要原理是把单相电经过电源变压器、整流电路、滤波电路、稳压电路转换成稳定的直流电压。由于输入电压为电网电压,一般情况下所需直流电压的数值和电网电压的有效值相差较大,因而电源变压器的作用显现出来起到降压作用。降压后还是交流电压,所

以需要整流电路把交流电压转换成直流电压。由于经整流电路整流后的电压含有较大的交流分量,会影响到负载电路的正常工作。需通过低通滤波电路滤波,使输出电压平滑。稳压电路的功能是使输出直流电压基本不受电网电压波动和负载电阻变化的影响,从而获得稳定性足够高的直流压。

9心得体会

本设计从经济实用的角度出发,采用美国Atmel公司的单片机AT89S51与低功耗CMOS型E2PROM AT24C02作为主控芯片与数据存储器单元,结合外围的键盘输入、显示、报警等电路并用汇编编写主控芯片的控制程序,研制了一款可以多次更改密码具有报警功能的电子密码锁。设计完全可行可以达到设计目地。使用单片机制作的电子密码锁具有软硬件设计简单,易于开发,成本较低,安全可靠,操作方便等特点,可应用于住宅、办公室的保险箱及档案柜等需要防盗的场所,有一定的实用性。该电路设计还具有按键有效提示,输入错误提示,控制开锁电平,控制报警电路,修改密码等多种功能。可在意外泄密的情况下随时修改密码。保密性强,灵活性高,特别适用于家庭、办公室、学生宿舍及宾馆等场所

10源程序

#include #include #define LCM_Data P0 #define uchar unsigned char #define uint unsigned int #define w 6

//定义密码位数

sbit lcd1602_rs=P2^5; sbit lcd1602_rw=P2^6; sbit lcd1602_en=P2^7; sbit Scl=P3^4; sbit Sda=P3^5;

//24C02串行时钟 //24C02串行数据 //报警

sbit ALAM = P2^1; sbit KEY = P2^0; sbit open_led=P2^2; bit operation=0; bit pass=0;

//开锁

//开锁指示灯

//操作标志位 //密码正确标志 //重置输入充许标志

//3秒按键标志位 //锁定键盘标志

bit ReInputEn=0; bit s3_keydown=0; bit key_disable=0;

unsigned char countt0,second; //t0中断计数器,秒计数器 void Delay5Ms(void);

unsigned char code a[]={0xFE,0xFD,0xFB,0xF7};

//控盘扫描控制表

unsigned char code start_line[] = {\ %unsigned char code name[]

= {\

unsigned char code Error[] = {\ error \ unsigned char code Locktrue[] = {\ true \

unsigned char code SetNew[] = {%unsigned char code Input[] = {\ \ unsigned char code ResetOK[] = {%unsigned char code initword[] = {%unsigned char code Er_try[] = {%unsigned char code again[] = {\ %unsigned char InputData[6];

unsigned char CurrentPassword[6]={1,3,1,4,2,0};

unsigned char TempPassword[6]; unsigned char N=0;

//密码输入位数记数 unsigned char ErrorCont; //错误次数计数 unsigned char CorrectCont;

//正确输入计数 unsigned char ReInputCont;

//重新输入计数

unsigned char code initpassword[6]={1,2,3,4,5,6}; void Delay5Ms(void)

{unsigned int TempCyc = 5552;

while(TempCyc--);}

void Delay400Ms(void) {unsigned char TempCycA = 5; unsigned int TempCycB; while(TempCycA--) {TempCycB=7269; while(TempCycB--);}} void mDelay(uint t) //延时 { uchar i; while(t--)

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

{;}}}

void Nop(void)

//空操作

{ _nop_(); _nop_(); _nop_();

_nop_();}

/*起始条件*/ void Start(void) { Sda=1;

Scl=1;

//显示名称 //输入错误 //输入正确

//INPUT

//输入密码暂存区 //当前密码值

Nop(); Sda=0; Nop();}

/*停止条件*/ void Stop(void) { Sda=0;

Scl=1; Nop(); Sda=1; Nop();}

/*应答位*/ void Ack(void) { Sda=0;

Nop(); Scl=1; Nop(); Scl=0;}

/*反向应答位*/ void NoAck(void) { Sda=1;

Nop(); Scl=1; Nop(); Scl=0;}

/*发送数据子程序,Data为要求发送的数据*/ void Send(uchar Data) { uchar BitCounter=8;

uchar temp; do

{ temp=Data;

Scl=0; Nop();

if((temp&0x80)==0x80) Sda=1; else Sda=0; Scl=1;

temp=Data<<1; Data=temp; BitCounter--;}

while(BitCounter); Scl=0;}

/*读一字节的数据,并返回该字节值*/ uchar Read(void)

{ uchar temp=0;

uchar temp1=0; uchar BitCounter=8; Sda=1; do{ Scl=0; Nop(); Scl=1; Nop(); if(Sda)

temp=temp|0x01; else

temp=temp&0xfe; if(BitCounter-1) {temp1=temp<<1; temp=temp1;} BitCounter--;} while(BitCounter); return(temp);}

void WrToROM(uchar Data[],uchar Address,uchar Num) { uchar i; uchar *PData; PData=Data; for(i=0;i

Send(Address+i); Ack();

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

void RdFromROM(uchar Data[],uchar Address,uchar Num) { uchar i; uchar *PData; PData=Data; for(i=0;i

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

Send(0xa1); Ack();

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

#define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80) #define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40) void delay(uint xms)//延时函数,有参函数 {uint x,y;

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

void write_1602com(uchar com)//****液晶写入指令函数**** { lcd1602_rs=0;//数据/指令选择置为指令

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

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

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

void write_1602dat(uchar dat)//***液晶写入数据函数**** { lcd1602_rs=1;//数据/指令选择置为数据

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

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

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

void lcd_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; //确定行线 else {return 0;}

i=0; P1=a[i]; while(i<4)

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

{col=~(P1&0xff); //确定列线 else {i++;

P1=a[i];}}} break;}

//精确定位

while((P1&0xf0)!=0xf0); return (row|col);}

else return 0;}

void OneAlam(void) {ALAM=0;

Delay5Ms();

ALAM=1;} void TwoAlam(void) { ALAM=0;

Delay5Ms();

ALAM=1; Delay5Ms();

ALAM=0; Delay5Ms();

ALAM=1;} void ThreeAlam(void)

{ ALAM=0;

Delay5Ms();

ALAM=1; Delay5Ms();

ALAM=0; Delay5Ms();

ALAM=1; Delay5Ms();

ALAM=0; Delay5Ms();

ALAM=1;} void DisplayOne(void) {write_1602com(yi+5+N);

write_1602dat('*');}

void DisplayChar(void) {unsigned char i;

if(pass==1)

{write_1602com(er); else {if(N==0)

{write_1602com(er); else

{write_1602com(er);

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

{write_1602dat(start_line[i]);}}}} for(i=0;i<16;i++)

{write_1602dat(Error[i]); }} for(i=0;i<16;i++)

{write_1602dat(Locktrue[i]);

}}

void DisplayInput(void) { unsigned char i;

if(CorrectCont==1) { write_1602com(er);

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

{write_1602dat(Input[i]); }}}

void ResetPassword(void) { unsigned char i;

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

{if(ReInputEn==1)

DisplayChar(); ThreeAlam();}

{if(N==6)

{ReInputCont++;

if(ReInputCont==2) {for(i=0;i<6;)

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

else

{write_1602com(er);

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

{write_1602dat(Error[j]); } ThreeAlam(); pass=0; ReInputEn=0; ReInputCont=0; DisplayChar(); break;}}

//关闭重置功能,

//错误提示

i++;

if(i==6)

{write_1602com(er);

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

{write_1602dat(ResetOK[j]); TwoAlam();

}

//操作成功提示

//将新密码写入24C02存储

else

WrToROM(TempPassword,0,6); ReInputEn=0;}

ReInputCont=0; CorrectCont=0;}

{OneAlam(); 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;}}}}

void Alam_KeyUnable(void) {P1=0x00;

{ALAM=~ALAM;

Delay5Ms();}}

void Cancel(void) {

unsigned char i; unsigned char j; 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); else

{ TR0=1;

//开启定时 //锁定键盘

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

{write_1602dat(Error[i]); } do

Alam_KeyUnable(); while(1);}

//错误输入计数达三次时,报警并锁定键盘

//重置密码功能未开启

key_disable=1; pass=0; break;}}}

if(i==6)

{CorrectCont++;

if(CorrectCont==1) {write_1602com(er);

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

{write_1602dat(Locktrue[j]); TwoAlam();

}

//正确输入计数,当只有一次正确输入时,开锁,

//操作成功提示音

KEY=0; pass=1; TR0=1;

//开锁 //置正确标志位 //开启定时

open_led=0; for(j=0;j<6;j++)

//开锁指示灯亮

//将输入清除

{InputData[i]=0;}}

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

else

{write_1602com(er);

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

{write_1602dat(SetNew[j]); TwoAlam(); ReInputEn=1; CorrectCont=0;}}

}

//操作成功提示

//允许重置密码输入

else

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

Data[5]==0))

{WrToROM(initpassword,0,6); else

{write_1602com(er);

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

{write_1602dat(Error[j]); } ThreeAlam(); pass=0;}}}

//错误提示音

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

{write_1602dat(initword[j]);} TwoAlam(); Delay400Ms(); TwoAlam(); N=0;}

//强制将初始密码写入24C02存储

else

{write_1602com(er); else

for(j=0;j<16;j++) {write_1602dat(Er_try[j]); ThreeAlam();}}

}

{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 KEY,NUM;

KEY=keynum(); if(KEY!=0) {if(key_disable==1)

{second=0;} else

{NUM=coding(KEY);

{switch(NUM)

{ case ('A'): ;

case ('B'):

break;

break;

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)

else

ALAM=1;

//关报警

Alam_KeyUnable();

//初始化数据输入位数

;

case ('C'): ; break;

case ('D'): ResetPassword(); case ('*'): Cancel(); case ('#'): Ensure(); default: {

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

break; //重新设置密码 break; //取消当前输入

break;

//确认键,

{write_1602dat(Input[i]);}

operation=0; if(N<6) { OneAlam();

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

write_1602dat('*');}

InputData[N]=NUM;

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;}}}

N++;}

else

{N=6;

break;}}}}}} }}

//关指示灯

//关定时器

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

Top