单片机实现电子密码锁实验二.docx

上传人:b****5 文档编号:10167891 上传时间:2023-02-09 格式:DOCX 页数:20 大小:412.16KB
下载 相关 举报
单片机实现电子密码锁实验二.docx_第1页
第1页 / 共20页
单片机实现电子密码锁实验二.docx_第2页
第2页 / 共20页
单片机实现电子密码锁实验二.docx_第3页
第3页 / 共20页
单片机实现电子密码锁实验二.docx_第4页
第4页 / 共20页
单片机实现电子密码锁实验二.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

单片机实现电子密码锁实验二.docx

《单片机实现电子密码锁实验二.docx》由会员分享,可在线阅读,更多相关《单片机实现电子密码锁实验二.docx(20页珍藏版)》请在冰豆网上搜索。

单片机实现电子密码锁实验二.docx

单片机实现电子密码锁实验二

<<单片机C语言>>实验二单片机实现电子密码锁

人们在日常生活,工作过程中越来越离不开密码的使用,比如新型小区单元门的电子密码锁,超市的储存柜,智能取款机,公司转帐交易等,这些时候人们接触到的都是一种使用电子密码的装置.电子密码的应用虽然广泛,但是基本原理都大体相同.

一.任务说明

一个简单的电子密码锁就是一个小型的单片机系统.它应该有输入设备,用户可以输入密码并确定或取消;应该有输出设备,用户可以看到显示自己输入正确与否的提示,输出设备还应该包括告警提示.电子密码锁内部的单片机是核心处理设备,它负责获取用户输入的密码,将其和正确的预置密码比较,产生相应的输出.若基于安全角度的考虑,可以让单片机记录下用户输入错误密码的次数,若此次数超过限制,则要采取相应的保护措施,防止他人反复试探密码.

本任务实现一个简单的电子密码锁,用4*4键盘组成0-9数字键以及确认,取消功能键,用4位8段数码管组成显示电路提示信息,其工作过程如下.

●加电后,显示”8888”.

●输入密码时,只逐位显示”F”,以防止泄漏密码.

●输入密码过程中,如果不小心出现输入错误,可按”取消”键清除屏幕,取消此次输入,此时显示”8888”.再次输入需重新输入所有4位密码.

●当密码输入完毕按下”确认”键时,单片机将输入的密码与设定的密码比较,若密码正确,则绿色发光二极管1秒钟(此次表示密码锁打开);若密码不正确,则红色发光二极管亮1秒钟.

二.设计思路分析

经过分析可知,设计具备上述功能的电子密码锁主要需要解决3个问题.

*键盘输入

*数码管显示

*单片机电路以及密码比较与处理的有关程序设计.

1.键盘输入

键盘是一组按键的集合,它是最常用的单片机输入设备.键盘可以分为两类:

独立连接式和矩阵式.

矩阵式键盘,也就是通常所讲的行列式键盘,由航线和列线组成,按键位于行列的交叉点上,行.列分别连接到按键开关的两端,行线通过上拉电阻接到高电平.无按键动作时,行线处于高电平状态;有按键按下时,交点的行线和列线接通,行线电平状态将由与此行线的列线电平决定.列线电平如果低,则行线电平低;列线电平高,则行线电平就高.这一点是识别矩阵键盘按键是否被按下的关键所在.

通过行列键盘扫描的方法可获取键盘输入的键值,从而得知按下的是哪个按键,具体过程如下.

(1)查询是否有键按下.单片机向行扫描口输出全为”0”的扫描码,然后从列检测口检测信号,只要有一列信号不为”1”,则表示有键按下,且不为”1”的列即对应为按下的键所在的列.

(2)查询按下键所在的行,列位置.前面已经取得了按下键的列号,接下来要确定键所在的行,这需要进行逐行扫描.单片机首先使第一行为”0”,其余个行为”1”,接着进行列检测,若为全”1”,表示不在第一行,否则即在第一行;然后使第二行为”0”,其余各行为”1”,再进行列检测,若为全”1”,表示不在第二行,否则即在第二行;这样逐行检测,直到找到按下键所在的行.当各行都扫描以后仍没有找到,则放弃扫描,认为是键的误动作.

(3)对得到的行号和列号进行译码,得到键值.对于4*4的行列式键盘,因为按键的位置由行号和列号唯一确定,且行列各四位,所以用一个字节(8位)来对键值编码是很合适的.本任务中,将字节的高四位(D7,D6,D5,D4)表示列号(4,3,2,1),低4位(D3,D2,D1,D0)表示行号(4,3,2,1),比如11H(00010001)表示第一行第一列,21H(00100001)表示第一行第二列,24H(00100100)表示第三行第二列.

在扫描键过程中,应注意以下问题.

消除键抖动等

对应上面的键盘及键盘的键值编码方法,各按键及其编码的对应关系如下表所示:

按键行号列号键值编码

01111H(00010001)

11221H(00100001)

21341H(01000001)

31481H(10000001)

42112H(00010010)

52222H(00100010)

62342H(01000010)

72482H(10000010)

83114H(00010100)

93224H(00100100)

确认3344H(01000100)

取消3484H(10000100)

 

2数码管显示

八段数码管由8个发光二极管LED组成,每一个LED称为一字段,共8段:

a,b,c,d,e,f,g,dp,其中dp为小数点,如上图所示:

八段数码管可以显示包括小数点的0-9数字和部分的英文字母.为了获得不同的字型,数码管各段锁加的电平也不同,编码也不一样.字型字段和编码的关系如下表所示(以共阴极数码管为例)

字型

D7

D6

D5

D4

D3

D2

D1

D0

编码

dp

g

f

e

d

c

b

a

0

0

0

1

1

1

1

1

1

3F

1

0

0

0

0

0

1

1

0

06

2

0

1

0

1

1

0

1

1

5B

3

0

1

0

0

1

1

1

1

4F

4

0

1

1

0

0

1

1

0

66

5

0

1

1

0

1

1

0

1

6D

6

0

1

1

1

1

1

0

1

7D

7

0

0

0

0

0

1

1

1

07

8

0

1

1

1

1

1

1

1

7F

9

0

1

1

0

1

1

1

1

6F

A

0

1

1

1

0

1

1

1

77

B

0

1

1

1

1

1

0

0

7C

C

0

0

1

1

1

0

0

1

39

D

0

1

0

1

1

1

1

0

5E

E

0

1

1

1

1

0

0

1

79

F

0

1

1

1

0

0

0

1

71

单片机驱动LED数码管有静态显示和动态扫描显示两种方法,其中后者较为常用.

动态扫描方法是用其接口电路把所有显示器的8个笔画字段(a-g和dp)同名端连接在一起,而每一个显示器的公共极COM各自独立的接受I/O线控制.CPU向字段输出端口输出字型码时,所有显示器接收到相同的字型码,但究竟使用哪个显示器,则取决与COM端,而这一端是由I/O控制的,由单片机决定何时显示哪一位.动态扫描用分时的方法轮流控制各个显示器的COM端,使各个显示器轮流点亮.

 

三.硬件电路设计

本任务的硬件电路是51单片机系统的典型电路,由单片机,键盘输入,数码管及指示灯输出三部分构成.

1结构框图

2主要器件

本任务使用的主要器件如下:

(1)单片机,它接收键盘的输入并作出判断,控制4位8段数码管和LED指示灯的显示.

(2)4*4行列式键盘.用户通过键盘输入4位密码及确认,取消功能键.

(3)8段数码管.共4位数码管,对应于4位密码.

(4)LED指示灯,红绿两个LED指示灯,红灯表示输入密码错误,绿灯表示输入密码正确,锁打开.

(5)CMOS六反相驱动器CD4069UB.CD4069UB对单片机的P2.0-P2.5进行反相操作以提供正确的数码管位选择信号,它可以提供足够的驱动电流.

3电路原理图及说明

系统的电路图分为3部分:

一是单片机及键盘电路原理图,如图所示:

二是位驱动及指示灯电路原理图,如图所示:

三是4位8段数码管显示电路原理图,如图所示:

 

 

说明:

U1为单片机芯片,它是整个电路的核心器件,联系着输入和输出.

P1口用于键盘操作,P1.0-P1.3与行线相连,R2-R5为行线的上拉电阻,P1.4-P1.7与列线相连.

P0口用作8段数码管的字段选择信号,控制数码管的字段LED发光,RP1为220欧的上拉排组.

P2口的P2.0-P2.3用于产生4位数码管的位选择信号,控制应该显示的8段数码管发光,位选择信号C1-C4需由P2.0-P2.3经由6反相器CD4096UB反相驱动.

P3.0P3.1作普通I/O口使用,前者控制绿色发光二极管,指示密码输入正确状态;

后者控制红色发光二极管,指示密码输入错误状态.

 

四.软件设计

软件可分为两部分.

1键盘输入.通过行列键盘扫描程序获取所按键的行,列号,并根据表1得到其键值编码.注意:

在键盘扫描时需进行消抖处理.

2数码管显示和指示灯输出.根据获取的键值编码,选择相应的功能,驱动数码管和指示灯显示.

五.程序流程

 

六.程序详解

 

#ifndef_PWLOCK_H//防止PWLock.h被重复引用

#define_PWLOCK_H

#include

#include

#include

#include

#defineucharunsignedchar

#defineuintunsignedint

uchardigbit;//字位

ucharwordbuf[6];//字型码缓冲区

uchart1count;//定时器1由50ms累积到1s所用的计数器

ucharcount;//密码位计数

ucharpw[6];//初始密码存储区

ucharpwbuf[6];//输入密码存储区

bitenterflag;//确认键按下与否标志

bitpwflag;//密码正确与否标志

bitshowflag;//数码管显示与否标志

sbitgreen=P3^0;

sbitred=P3^1;

voiddisplay(void);//显示函数

#endif

 

#include"PWLock.h"

/*键消抖延时函数*/

voiddelay(void)

{

uchari;

for(i=300;i>0;i--);

}

/*键扫描函数*/

ucharkeyscan(void)

{

ucharscancode,tmpcode;

P1=0xf0;//发全0行扫描码

if((P1&0xf0)!

=0xf0)//若有键按下

{

delay();//延时去抖动

if((P1&0xf0)!

=0xf0)//延时后再判断一次,去除抖动影响

{

scancode=0xfe;

while((scancode&0x10)!

=0)//逐行扫描

{

P1=scancode;//输出行扫描码

if((P1&0xf0)!

=0xf0)//本行有键按下

{

tmpcode=(P1&0xf0)|0x0f;

/*返回特征字节码,为1的位即对应于行和列*/

return((~scancode)+(~tmpcode));

}

elsescancode=(scancode<<1)|0x01;//行扫描码左移一位

}

}

}

return(0);//无键按下,返回值为0

}

/*定时器0中断服务子程序,2ms定时动态扫描显示*/

voidtime0_int(void)interrupt1

{

/*重置2ms定时*/

TH0=65536-2000/256;

TL0=65536-2000%256;

if(showflag==1)

display();//调用显示函数

}

/*定时器1中断服务子程序,50ms*/

voidtime1_int(void)interrupt3

{

uchark;

/*重置50ms定时*/

TH1=65536-50000/256;

TL1=65536-50000%256;

if(t1count<20)

{

t1count++;

}

else//计时到1s

{

TR1=0;//关闭计数器1

t1count=0;

green=1;//绿灯不亮

red=1;//红灯不亮

showflag=1;//打开数码管显示

digbit=0x01;//从数码管第1位开始动态显示

for(k=0;k<4;k++)//显示8888

wordbuf[k]=8;

}

}

/*根据共阴极字型编码表获取0~9,A~B字型代码*/

uchargetcode(uchari)

{

ucharp;

switch(i)

{

case0:

p=0x3f;break;/*0*/

case1:

p=0x06;break;/*1*/

case2:

p=0x5B;break;/*2*/

case3:

p=0x4F;break;/*3*/

case4:

p=0x66;break;/*4*/

case5:

p=0x6D;break;/*5*/

case6:

p=0x7D;break;/*6*/

case7:

p=0x07;break;/*7*/

case8:

p=0x7F;break;/*8*/

case9:

p=0x67;break;/*9*/

case10:

p=0x77;break;/*A*/

case11:

p=0x7C;break;/*B*/

case12:

p=0x39;break;/*C*/

case13:

p=0x5E;break;/*D*/

case14:

p=0x79;break;/*E*/

case15:

p=0x71;break;/*F*/

default:

break;

}

return(p);

}

/*显示函数*/

voiddisplay(void)

{

uchari;

switch(digbit)

{

case1:

i=0;break;

case2:

i=1;break;

case4:

i=2;break;

case8:

i=3;break;

default:

break;

}

P2=0x0;//关闭显示

P0=getcode(wordbuf[i]);//送字型码

P2=digbit;//送字位码

if(digbit<0x08)//共4位

digbit=digbit*2;//左移一位

else

digbit=0x01;

}

/*密码比较函数*/

bitpwcmp(void)

{

bitflag;

uchari;

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

{

if(pw[i]==pwbuf[i])

flag=1;

else

{

flag=0;

i=4;

}

}

return(flag);

}

/*主程序*/

voidmain()

{

ucharj,key;

P2=0x0;//关闭数码管显示

TMOD=0x11;//T0,T1工作方式1

/*2ms定时设置*/

TH0=-2000/256;

TL0=-2000%256;

/*50ms定时设置*/

TH1=-50000/256;

TL1=-50000%256;

/*启动计数器0,关闭计数器1*/

TR0=1;

ET0=1;

TR1=0;

ET1=1;

EA=1;

count=0;//初始没有输入密码,计数器设为0

enterflag=0;//没有按下确认键

pwflag=0;//密码标志先置为0

green=1;//绿灯不亮

red=1;//红灯不亮

/*假设内定密码为9376*/

pw[0]=9;

pw[1]=3;

pw[2]=7;

pw[3]=6;

digbit=0x01;//从第一位数码管开始动态扫描

/*刚加电时,显示8888*/

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

wordbuf[j]=8;

showflag=1;//打开数码管显示

while

(1)

{

key=keyscan();//调用键盘扫描函数

switch(key)

{

case0x11:

//1行1列,数字0

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F”

pwbuf[count]=0;

count++;

}

break;

case0x21:

//1行2列,数字1

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=1;

count++;

}

break;

case0x41:

//1行3列,数字2

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=2;

count++;

}

break;

case0x81:

//1行4列,数字3

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=3;

count++;

}

break;

case0x12:

//2行1列,数字4

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=4;

count++;

}

break;

case0x22:

//2行2列,数字5

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=5;

count++;

}

break;

case0x42:

//2行3列,数字6

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=6;

count++;

}

break;

case0x82:

//2行4列,数字7

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=7;

count++;

}

break;

case0x14:

//3行1列,数字8

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=8;

count++;

}

break;

case0x24:

//3行2列,数字9

if(count<4)

{

wordbuf[count]=0x0f;//对应密码位上显示“F"

pwbuf[count]=9;

count++;

}

break;

case0x44:

//3行3列,确认键

enterflag=1;//确认键按下

if(count==4)//只有输入4个密码后按确认键才作密码比较

pwflag=pwcmp();

else

pwflag=0;//否则直接pmflag赋0

break;

case0x84:

//3行4列,取消键

count=0;//密码计数清零

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

{

wordbuf[j]=8;//数码管显示8888

pwbuf[j]=0x0f;//用FFFF清除已经输入的密码

}

break;

default:

break;

}

if(enterflag==1)//如果按下确认键

{

enterflag=0;//标志位置回0

count=0;//密码位计数器清零

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

pwbuf[j]=0x0f;//用FFFF清除已经输入的密码

showflag=0;//关闭数码管显示

TR1=1;//计数器1开始计数

t1count=0;//定时器1由50ms累积到1s所用的计数器

if(pwflag==1)

green=0;

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 表格模板 > 表格类模板

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1