收藏 分销(赏)

单片机密码锁实验报告.doc

上传人:快乐****生活 文档编号:4744106 上传时间:2024-10-11 格式:DOC 页数:20 大小:4.62MB 下载积分:10 金币
下载 相关 举报
单片机密码锁实验报告.doc_第1页
第1页 / 共20页
单片机密码锁实验报告.doc_第2页
第2页 / 共20页


点击查看更多>>
资源描述
二○一六~二○一七学年第 一 学期 电子信息工程系 电子综合设计II 报告书 班 级: 电信(产业)1401班 设计时间: 2016/12/29 学生姓名: 曹子龙 学 号: 201404135024 指导教师: 赵敏 二○一六年 十二 月 一、 设计要求. 题目内容: 设计一个基于51单片机的电子密码锁: 1. 可以使用4*4的矩阵键盘与红外遥控器输入密码。 2. 可以通过按特殊组合键重设开锁密码。 3. 显示通过1602液晶屏显示电子密码锁界面,输入密码时显示输入个数显示为‘*’,如果密码正确,进入欢迎界面。 4. 密码连续输入3次错误报警,LCD显示报警,倒计时十秒后重新进入密码输入界面。 5. 可以通过特殊的按键组合跳过输入界面直接进入欢迎界面。 实现方法: 1. 通过红外接收头,连接单片机的P3.2外部中断INT0口,可以实现单片机接收遥控器的信号输入。 2. 通过矩阵键盘扫描函数,可以实现对键盘输入的响应。 3. 通过引脚的高低电平变化频率,控制蜂鸣器的输入占空比和频率(低电平时间固定,通过输入给函数值的不同改变高电平时间,固定响300个周期),对不同按键实现不同声音响应。 4. 1602显示屏有16*2个单元格,每个单元格由5*8个像素点组成,可以很好的显示数字,符号,英文字符。 功能需求分析: 液晶屏显示: 根据题意,需要设计并显示输入密码界面、修改密码界面、欢迎界面、错误警告界面 密码输入: 根据题意,每次输入一个数字,则显示一个‘*’符号代替,只能看出输入的位数,若输入密码位数达到六位,则与正确密码比较,若正确,进入系统。根据日常的手机使用习惯,默认长度为6位,且第六位输入之后立即判断,正确则进入,错误则清空重输。 组合键实现密码修改: 密码修改必须通过不易被他人发现的特殊方法改变,所以设计为,若同时按住矩阵键盘的5,10 或6,9两个键,则进入密码修改函数。 输入密码错误三次则报错: 一般的密码系统对密码输入错误次数过多的情况进行了限制,所以在密码锁里设置,若密码输入错误三次,则进入警报界面,显示10s倒计时,必须在倒计时结束后才能再次输入密码。 组合键实现跳过密码: 如果系统主人临时忘记了密码,则需要一些补救的备用措施,所以在电子锁里设计了,如果同时按下0,15或3,12键,则跳过密码输入阶段,直接进入欢迎界面。 红外控制: 在很多时候,需要通过远程通信输入密码,进入某个远程服务器系统。所以,通过红外设备模拟远程通信就显得很有必要。再此系统中,通过把红外接收引脚接到外部中断INT0口,实现接收红外遥控器的数据。 重新输入: 如果密码输入的过程中,发现输错了一位数,方便起见,要设置重新输入的功能,即矩阵按键为11,或红外遥控键值为12时,重新输入密码,并且不计入输错次数。 二、 系统总体设计框架 系统模块分布图: 详细流程框图: 三、 运行结果 密码输入: 每次输入一个数字,则显示一个‘*’符号。 密码修改: 通过特殊组合按键,进入密码修改函数。 三次报错: 若密码输入错误三次,则进入警报界面。 特殊键清除: 通过特殊组合按键,进入密码修改函数。 红外控制: 通过红外遥控器输入密码。 重新输入: 通过红外遥控器的12号按键或矩阵键盘的11号按键可以重新输入密码。 四、 实验小结 本次实验,用51单片机实现了电子密码锁系统,虽然内容较基础,但是还是新学到了一些新知识,如红外线的数据传输方式,外部中断的合理使用。 同时也遇到了一些问题: 用红外遥控器输入密码的时候,总会在短时间内把一个键值发给单片机发送两次,但是原因不是太清楚,可能是红外遥控器的抬起也算一个命令,然后我再判断主函数的红外线标志位判断的地方,加了0.5秒的延迟,解决了问题。以后有时间再把红外接收器的数据手册详细看看,研究问题出在哪里。 总体来说,这一次的动手设计还是让自身能力提高了不少,但其实我学习的东西还远远不够,在以后的学习里,我会抓紧课外时间多学习知识,才能将自身解决实际问题的能力快速提高。 五、 参考文献 [1] 谭浩强,C语言程序设计,清华大学出版社,2005 [2] 张毅刚,单片机原理及接口技术,人民邮电出版社,2011 六、 附录:源程序 /******************************************************************************* * 电子密码锁系统 Designed By 曹子龙 2016/12/29 * *******************************************************************************/ #include<reg51.h> #include"lcd.h" //包含控制1602的初始化程序及写入命令的程序 #define GPIO_KEY P1 //矩阵键盘接口 sbit IRIN=P3^2; //红外线接口 sbit Beep = P2^0; //蜂鸣器接口 unsigned char code CDIS0[16]={" Set Code: "}; //用来初始化1602屏幕显示内容的字符串数组 unsigned char code CDIS1[16]={" Enter Code: "}; unsigned char code CDIS2[16]={" Code: "}; unsigned char code CDIS3[16]={" Welcome to "}; unsigned char code CDIS4[16]={" My System!"}; unsigned char code CDIS5[16]={" Warning: "}; unsigned char code CDIS6[16]={" Please Wait s!"}; unsigned int RIGHTCODE[6]={9,7,0,2,2,9};//初始正确密码 unsigned int Code[6]; //用来存放输入密码 unsigned int KeyValue; //用来储存键值 unsigned int Key_Flag=0; //有按键按下时置为1 unsigned int HongwaiValue; //用来储存键值 unsigned int Hongwai_Flag=0; //有红外信号时置为1 unsigned int Annum=0; //用来储存按键次数 unsigned int Wrongnum=0; //用来储存错误次数 unsigned int CodeFlag=0; //用来标识密码是否输入正确 unsigned int CodeDel=0; //特殊组合键可以清除密码 unsigned char IrValue[6]; //暂存接收到的红外信号 unsigned char Time; unsigned char WrongTime; //用来储存错误等待时间 void SetCode(); //重置密码函数 void hongwai(); //将红外接收的值变为对应的按键值 void IrInit(); //红外初始化 void DelayMs(unsigned int ); void beep(unsigned int); //可让蜂鸣器实现不同频率声音的函数 void KeyScan(); //键盘扫描函数 /******************************************************************************* * 函数名 : main * 函数功能 : 主函数 *******************************************************************************/ void main() { unsigned char i; IrInit(); LcdInit(); LcdWriteCom(0x80); //初始化LCD1602显示,展示密码输入界面 for(i=0;i<16;i++) { LcdWriteData(CDIS1[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } while(1) { KeyScan(); //扫描键盘 if(CodeDel==4) //若输入正确的组合按键,可重设密码 SetCode(); else if(CodeDel==2) //若输入正确的组合按键,则清除密码,直接进入系统 { Wrongnum=0; //若输入正确,错误次数清零 Annum=0; //密码计数器清零 CodeDel=0; //组合键标志位清0 Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 LcdWriteCom(0x80); //进入欢迎界面 5s for(i=0;i<16;i++) { LcdWriteData(CDIS3[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS4[i]); } DelayMs(50000); LcdWriteCom(0x80); for(i=0;i<16;i++) //等待结束后,次数清零,显示输入密码界面 { LcdWriteData(CDIS1[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } } if(Key_Flag==1) { Key_Flag=0; Code[Annum-1]=KeyValue; //将输入值存入密码数组中 beep(KeyValue * 30); LcdWriteCom(0xc0+6+Annum); LcdWriteData(42); } if(Hongwai_Flag==1) //若接受到了红外数据 { DelayMs(500); if(Hongwai_Flag==1) //不知道因为什么原因,红外接收的中断会开启两次,为了防止数据重复,写了此次延时判断 { Annum++; //按键次数加1 Hongwai_Flag=0; Code[Annum-1]=HongwaiValue;//将输入值存入密码数组中 beep(HongwaiValue * 40); LcdWriteCom(0xc0+6+Annum); LcdWriteData(42); } } if(Annum>=6) //6位密码输入完毕或检测到特殊组合按键 { CodeFlag=1; //暂时令标志位为1,若密码有错误,则再置0 for(i=0;i<6;i++) { if(Code[i]!=RIGHTCODE[i]) //若密码与正确密码不相等 CodeFlag=0; } if(CodeFlag==0) //若输入错误,清零重新输入,并将错误输入次数加一 { Wrongnum++; if(Wrongnum==3) //若错误次数达到三次 { beep(100); //警报 LcdWriteCom(0x80); //显示错误信息,等待10s for(i=0;i<16;i++) { LcdWriteData(CDIS5[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS6[i]); } WrongTime='9'; //等待时间 while(WrongTime!='0') { LcdWriteCom(0x80+0x40+13); LcdWriteData(WrongTime); DelayMs(10000); WrongTime--; } Wrongnum=0; } Annum=0; Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 LcdWriteCom(0x80); for(i=0;i<16;i++) //等待结束后,次数清零,显示输入密码界面 { LcdWriteData(CDIS1[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } } if(CodeFlag==1) //密码输入正确 { Wrongnum=0; //若输入正确,错误次数清零 Annum=0; //密码计数器清零 LcdWriteCom(0x80); //进入欢迎界面 5s for(i=0;i<16;i++) { LcdWriteData(CDIS3[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS4[i]); } DelayMs(50000); LcdWriteCom(0x80); for(i=0;i<16;i++) //等待结束后,次数清零,显示输入密码界面 { LcdWriteData(CDIS1[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } /*标志清零需放在后面,因为在密码输入正确后的显示时间内, 外部中断或按键都会使标志位为1,进而在再次显示密码时弹出一位密码值*/ Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 } } } } /******************************************************************************* * 函数名 : SetCode() * 函数功能 : 设置密码 *******************************************************************************/ void SetCode() { int i,j=0; Wrongnum=0; //错误次数清零 Annum=0; //密码计数器清零 CodeDel=0; //组合键标志位清0 Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 LcdWriteCom(0x80); for(i=0;i<16;i++) //初始化LCD1602显示,显示设置密码界面 { LcdWriteData(CDIS0[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } DelayMs(1000); while(j<6) { KeyScan(); //扫描键盘 if(Key_Flag==1) { Key_Flag=0; RIGHTCODE[j]=KeyValue; beep(KeyValue * 30); LcdWriteCom(0xc0+7+j); LcdWriteData(42); j++; DelayMs(1000); } if(Hongwai_Flag==1) //若接受到了红外数据 { DelayMs(500); if(Hongwai_Flag==1) //不知道因为什么原因,红外接收的中断会开启两次,为了防止数据重复,写了此次延时判断 { Hongwai_Flag=0; RIGHTCODE[j]=HongwaiValue; beep(HongwaiValue * 40); LcdWriteCom(0xc0+7+j); LcdWriteData(42); j++; DelayMs(1000); } } } LcdWriteCom(0x80); for(i=0;i<16;i++) //初始化LCD1602显示,展示密码输入界面 { LcdWriteData(CDIS1[i]); } LcdWriteCom(0x80+0x40); for(i=0;i<16;i++) { LcdWriteData(CDIS2[i]); } Wrongnum=0; //错误次数清零 Annum=0; //密码计数器清零 Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 } /******************************************************************************* * 函数名 : DelayMs() * 函数功能 : 延时 *******************************************************************************/ void DelayMs(unsigned int x) //0.14ms误差 0us { unsigned char i; while(x--) { for (i = 0; i<13; i++) {} } } /******************************************************************************* * 函数名 : IrInit() * 函数功能 : 初始化红外线接收 *******************************************************************************/ void IrInit() { IT0=1;//下降沿触发 EX0=1;//打开中断0允许 EA=1; //打开总中断 IRIN=1;//初始化端口 } /******************************************************************************* * 函数名 : ReadIr() * 函数功能 : 读取红外数值的中断函数 *******************************************************************************/ void ReadIr() interrupt 0 { unsigned char j,k; unsigned int err; Time=0; DelayMs(70); if(IRIN==0) //确认是否真的接收到正确的信号 { err=1000; //1000*10us=10ms,超过说明接收到错误的信号 /*当两个条件都为真是循环,如果有一个条件为假的时候跳出循环,免得程序出错的时 侯,程序死在这里*/ while((IRIN==0)&&(err>0)) //等待前面9ms的低电平过去 { DelayMs(1); err--; } if(IRIN==1) //如果正确等到9ms低电平 { Hongwai_Flag=1; //正确收到信号,标志位置1 err=500; while((IRIN==1)&&(err>0)) //等待4.5ms的起始高电平过去 { DelayMs(1); err--; } for(k=0;k<4;k++) //共有4组数据 { for(j=0;j<8;j++) //接收一组数据 { err=60; while((IRIN==0)&&(err>0))//等待信号前面的560us低电平过去 { DelayMs(1); err--; } err=500; while((IRIN==1)&&(err>0)) //计算高电平的时间长度。 { DelayMs(1);//0.14ms Time++; err--; if(Time>30) { EX0=1; return; } } IrValue[k]>>=1; //k表示第几组数据 if(Time>=8) //如果高电平出现大于565us,那么是1 { IrValue[k]|=0x80; } Time=0; //用完时间要重新赋值 } } hongwai(); } if(IrValue[2]!=~IrValue[3]) { return; } } } /******************************************************************************* * 函数名 : KeyScan * 函数功能 : 扫描矩阵键盘 *******************************************************************************/ void KeyScan(void) //读取按键值 { char a = 0; int j; GPIO_KEY=0x0f; if(GPIO_KEY!=0x0f)//读取按键是否按下 { DelayMs(10);//延时10ms进行消抖 if(GPIO_KEY!=0x0f)//再次检测键盘是否按下 { Key_Flag=1; Annum++; //按键次数加1 //测试行 GPIO_KEY=0X0F; switch(GPIO_KEY) { case(0X07): KeyValue=12;break; case(0X0b): KeyValue=8;break; case(0X0d): KeyValue=4;break; case(0X0e): KeyValue=0;break; case(0X06): CodeDel=1;break; //特殊按键组合可以清除密码 case(0X09): CodeDel=3;break; //特殊按键组合可以重设密码 } //测试列 GPIO_KEY=0XF0; switch(GPIO_KEY) { case(0X70): KeyValue=KeyValue+3;break; case(0Xb0): KeyValue=KeyValue+2;break; case(0Xd0): KeyValue=KeyValue+1;break; case(0Xe0): KeyValue=KeyValue;break; case(0X60): if(CodeDel==1) CodeDel=2;break; //按键0和15组合可以清除密码 case(0X90): if(CodeDel==3) CodeDel=4;break; //按键5和6组合可以重设密码 } while((a<50) && (GPIO_KEY!=0xf0)) //检测按键松手检测 { DelayMs(10); a++; } if(KeyValue==11) //11按键可以重新输入密码 { Annum=0; //密码计数器清零 Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 LcdWriteCom(0x80+0x40);//清除密码输入的*符号 for(j=0;j<16;j++) { LcdWriteData(CDIS2[j]); } } } } } /******************************************************************************* * 函数名 : hongwai * 函数功能 : 将接收到的16进制红外信号转化为0-12的键值 *******************************************************************************/ void hongwai() //根据红外线遥控器键值表,将接收的代码值转化为0-12的键值 { int j; IrValue[4]=IrValue[2]>>4; //高位 IrValue[5]=IrValue[2]&0x0f; //低位 if(IrValue[4]==1&&IrValue[5]==6) HongwaiValue=0; else if(IrValue[4]==0&&IrValue[5]==12) HongwaiValue=1; else if(IrValue[4]==1&&IrValue[5]==8) HongwaiValue=2; else if(IrValue[4]==5&&IrValue[5]==14) HongwaiValue=3; else if(IrValue[4]==0&&IrValue[5]==8) HongwaiValue=4; else if(IrValue[4]==1&&IrValue[5]==12) HongwaiValue=5; else if(IrValue[4]==5&&IrValue[5]==10) HongwaiValue=6; else if(IrValue[4]==4&&IrValue[5]==2) HongwaiValue=7; else if(IrValue[4]==5&&IrValue[5]==2) HongwaiValue=8; else if(IrValue[4]==4&&IrValue[5]==10) HongwaiValue=9; else if(IrValue[4]==1&&IrValue[5]==9) HongwaiValue=10; else if(IrValue[4]==0&&IrValue[5]==13) HongwaiValue=11; else HongwaiValue=12; if(HongwaiValue==11) //按键可以重新输入密码 { Annum=0; //密码计数器清零 Key_Flag=0; //按键标志位清0 Hongwai_Flag=0; //红外标志位清0 LcdWriteCom(0x80+0x40);//清除密码输入的*符号 for(j=0;j<16;j++) { LcdWriteData(CDIS2[j]); } } } void delay(unsigned int i) { char j; for(i; i > 0; i--) for(j = 200; j > 0; j--); } /******************************************************************************* * 函数名 : beep * 函数功能 : 可以实现不同频率和占空比的蜂鸣器鸣叫程序 *******************************************************************************/ void beep(unsigned int type) //按键值不同,对应蜂鸣器不同的声音 { unsigned int n = 300; while(n!=0) { Beep= 1; delay(25); Beep= 0; delay(type/20); n--; } }
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服