




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
摘要本系统根据大赛设计要求以STC89C52单片机为控制核心,自行设计了一套宿舍智能防盗防火报警系统。该系统分为烟雾检测和声光报警模块、人体检测和声光报警模块、宿舍人员进出及人数记录和无人提示锁门模块、密码解警模块和附加的时钟及外扩EEPROM模块。实现了当有火灾或者盗窃现象时启动报警、输入密码开门、输入密码解警、记录宿舍人员进出状况及无人启动报警提示锁门、记录宿舍安防记录模块等功能,同时在系统中额外加了时钟显示功能和保存密码功能,使系统更加多元化和智能化。系统方案论证及系统硬件设计根据题目的基本要求,设计任务主要完成实现人体检测与声光报警功能;实现烟雾检测与声光报警功能;用键盘输入密码完成报警系统的解警等工作状况;实现异地监控;能反映宿舍内人员的进出情况及人数的记录;宿舍无人时提示锁门。为完成相应功能,该系统有五大模块组成,即人体监测与声光报警模块、烟雾监测与声光报警模块、宿舍人员进出及人数记录和无人提示锁门模块、密码解警模块、宿舍安防记录模块,方案结构图如下所示:宿舍人员进出及人数记录和无人提示锁门模块宿舍人员进出及人数记录和无人提示锁门模块烟雾监测与声光报警模块人体监测与声光报警模块MCU烟雾监测与声光报警模块人体监测与声光报警模块MCU安防记录模块密码解警模块安防记录模块密码解警模块MCU选取方案在该系统的五个模块中都存在MCU的选取问题,MCU的性能和成本直接决定着整个系统的性能和成本。MCU的主要是对烟雾报警器及红外报警器的实时监控、对宿舍安防情况进行记录、对宿舍人员进出次数的记录和无人提示锁门及输入特定密码时达到解警的目的。因此可以有以下中MCU的选取方案。方案一:选用ARM芯片。ARM芯片是32位的处理器,运算速度快,并行端口多,可以实现复杂的功能,但是对于该系统来说,所需要的端口并不多,电路结构也不是很复杂,若使用ARM系列芯片定会增加电路的复杂程度及软件实现的复杂程度,而且这个系统选用ARM有点大材小用,且ARM系列芯片的价格也会使系统成本大幅度提升,故放弃此方案。方案二:选用FPGA(现场可编程门阵列)作为系统的控制器。FPGA作为新一代的可编程器件使得其应用较为灵活,功能从简单到复杂都可以实现,但是在该系统中,若使用FPGA则会提高系统的成本,同时由于增加的FPGA,也会给电路的维修工作带来不可必要的麻烦。方案三:选用宏晶公司的STC89C52单片机,STC89C52单片机是8位的单片机,有32个I/0构成,对于该系统来说端口足够使用,价格便宜,功耗低,且易于控制,因此将STC89C52作为MCU的最终选取方案。2.烟雾检测与声光报警模块该模块要实现的功能是当发生火灾时,烟雾会使烟雾传感器感应,使用比较器对传感器输出进行转换,使之通过比较器输出时为高低电平并输入给单片机的I/O口,通过单片机对输入口的电平采集来控制发生声光报警现象。经过我们的论证,出于在不影响整体功能的情况下尽量使系统结构简单,故传感器我们选用MQ-2,声光报警我们选用发光二极管和喇叭组成。MQ-2气体传感器所使用的气敏材料是在清洁空气中电导率较低的二氧化锡(SnO2)。当传感器所处环境中存在可燃气体时,传感器的电导率随空气中可燃气体浓度的增加而增大。使用简单的电路即可将电导率的变化转换为与该气体浓度相对应的输出信号。MQ-2/MQ-2S气体传感器对液化气、丙烷、氢气的灵敏度高,对天然气和其它可燃蒸汽的检测也很理想。这种传感器可检测多种可燃性气体,是一款适合多种应用的低成本传感器。 MQ-2的外形:我们所使用的MQ-2的电路图如下: 电源 正 10K烟雾报警器 负AHABHBAHABHB 负 输出 正 地 10K 地声光报警模块我们使用的电路图如下:单片机I/O口 单片机I/O口报警时启动声光报警器,LCD会显示:3.人体监测与声光报警模块该模块要是实现的功能是当监测到人进入宿舍时,会启动声光报警功能,直到有人输入密码后解除报警。监测人进入宿舍选用热释电人体红外开关。该电路的设计思路如下图示:MCU放大电路红外开关报警!MCU放大电路红外开关报警!我们所使用的红外开关电路图如下所示:热释电人体红外开关简介如下:热释电红外开关时BISS0001配以热释电红外传感器和少量外接元器件构成的被动式开关。它可用于我们的报警系统。热释电红外传感器是一种新型敏感元件、它是由高热电系数材料,配以滤光镜片和阻抗匹配用场效应管组成。它能以非接触方式监测出来自人体发出的红外辐射将其转换为电信号输出,并可抑制人体辐射波长以外的外干扰辐射,如阳光、灯光及其反射光。BISS0001是一款具有较高性能的传感信号处理集成电路。它的主要功能有:1)CMOS数模混合专用集成电路;2)具有独立的高输入阻抗运算放大器,可与多种传感器匹配,进行信号与处理;3)双向鉴幅器,可有效抑制干扰;4)内设延迟时间定时器和封锁时间定时器;5)结构新颖,稳定可靠,调解范围宽;6)内置参考电压;7)工作电压范围2V~6V;8)采用16脚DIP和SOP封装;9)PPLICATIONAPPLICATIONAPPLICATIONAPPLICATION产品应用;10)用于多种传感器和延时控制器。声光报警电路选用与烟雾监测与声光报警模块同一个电路图(具体电路见烟雾检测与声光报警模块的声光报警模块)。4.宿舍人员进出及人数记录和无人提示锁门模块(仿真已实现,但是实物未来得及做)该模块要实现当有人进入或有人出宿舍时,要对宿舍进出状况进行记录,并在无人的情况下(即进出次数相同时),提示锁门。监测人进或出时我们选用2对红外对管,当无人时红外对管输出处于高电平,当有人通过时红外对管输出低电平,单片机采集信号,当进出宿舍次数相等时,启动声光报警电路提示锁门,LCD也会显示pleaseclosedoor!由于数码管显示较为明显,我们为达到论文较为清晰的目的,第一次模拟时采用了数码管模拟,并用开关代替光电开关。模拟效果图如下:当无人时数码管为0,声光报警,如下所示:当用LCD代替数码管时,LCD显示如下:注:当1人进入时数码管数字加1,1人出去时数码管数字减1(如何实现见软件部分)。A、B模拟两对红外对管,分别在进门的两侧,A代表门外侧的一对,B代表门内侧的一对,人进门时是先进入外侧然后才能通过内侧的红外对管,软件编程即根据这一思想(如下面)。软件程序如下:#include<reg51.h>#defineuintunsignedint#defineucharunsignedcharucharcodetable[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};sbittip=P1^7;sbitA=P3^3;sbitBB=P3^5;ucharcount;voiddelay(){ uintx,y; for(x=100;x>0;x--) for(y=100;y>0;y--);}voidinit(){ count=0; P2=table[count];tip=0;}voidmain(){ init(); while(1) { P2=table[count]; if((!A)&&BB) { while((!A)&&BB); if((!A)&&(!BB)) { while((!A)&&(!BB)); if(A&&(!BB)) { while(A&&(!BB)); if(A&&BB) { count++; } } } } elseif((!BB)&&A) { while((!BB)&&A); if((!BB)&&(!A)) { while((!BB)&&(!A)); if(BB&&(!A)) { while(BB&&(!A)); if(BB&&A) { count--; P2=table[count]; } } } } if(count==0) tip=1; else tip=0; } }5.密码解警模块该模块要实现的功能是当发生声光报警时,无论是烟雾检测报警还是人体检测报警或是提示锁门报警,只有在输入密码的条件下才会取消报警。该模块的实现有两种方式,即采用双列直插的DIP开关、4x4矩阵键盘。采用双列直插的DIP开关比较简单,只需对1-8对各个按键进行编号,但是但是所设密码易于破解。而4x4矩阵键盘实现时电路的复杂程度会提高,但是密码不易破解,安全性高,处于这个角度的考虑,我们选用4x4的矩阵键盘实现解警功能。4x4矩阵键盘的硬件设计如下图示:键盘说明:A:解警键,当按下A键时,输入密码即可解警。LCD显示如右图:B:设置时间,按下B键可以修改时间,如图示:可以设置年的十位和个位,月和具体时间。C:用于修改密码,当按下C键时,修改原始密码。LCD显示如图:输入完旧密码时,LCD会显示:输入一次密码后,LCD会显示:输入两次密码后,设置新密码成功。新密码会存入AT24C02中,下次再次使用时,为新设的密码。D:解锁开门键,当输入密码时就会打开门,LCD会显示:E:用于显示宿舍安防记录的按键,当按下E时LCD会显示:再次按下就会显示宿舍安防记录类型,按任意键返回。1,2,3,4,5,6,7,8,9键均为数字键。6.宿舍安防记录模块利用外扩的EEPROM记录下宿舍的安防情况,通过键盘查找最近的安防记录,并将其显示在LCD上。如按下E键LCD会显示:再按下E键会显示最近的记录,如:继续按E键,会继续显示,会显示30次的安防记录。按任意键返回。TYPE与报警类别的对应关系如下:“1”:报火警(烟雾报警)“2”:有人强制进门(人体热释电报警)“3”:提示锁门“4”:解警开门7.其他模块1)为了丰富该系统的功能,我们在尽可能实现题目要求的基础上增加了实时时钟模块,利用DS1302这款芯片实现了实时时钟的设计,并将时间显示在LCD上,当对系统无任何操作时LCD显示时间,如下图示:DS1302简介如下:DS1302是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后背电源双电源引脚,同时提供了对后背电源进行涓细电流充电的能力。DS1302封装图如下示:2)为了保存新设的密码,我们在电路中增加了AT24C02的外扩的串行EEPROM。AT24C02是一个2K位串行CMOSE2PROM,内部含有256个8位字节,CATALYST公司的先进CMOS技术实质上减少了器件的功耗。AT24C02有一个16字节页写缓冲器。该器件通过IC总线接口进行操作,有一个专门的写保护功能。管脚图封装如下:AT24C02支持IC,总线数据传送协议IC,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式,通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上。当修改密码时,将新修改的密码读入AT24C02中,上电后再将密码从AT24C02中读出,可以达到保存密码的目的。假设修改后的密码为123456,则proteus仿真存入AT24C02的密码如下图:3)进门时必须输入密码才能打开门进入宿舍。当有人不输入密码强制开门时,LCD会显示报警如下图:当有人不输入密码又不从宿舍门进入时,LCD也会显示报警如下图:4)增加了解开键盘按键和门按键,当门键按下时为关门,不按下为开门,键盘键按下为解开键盘,可以对键盘进行操作。系统软件设计该系统采用C语言进行软件设计,C语言以其结构化和能产生高效代码满足了单片机应用系统日趋复杂的要求,并便于多人以软件工程的形式进行协同开发。采用C51程序设计语言,编程者只需了解变量和常量的存储类型与89C51单片机存储空间的对应关系,而不必深入了解单片机的硬件和接口,C51编译器会自动完成变量的存储单元的分配。软件总体框架开始开始存入AT24C02设置新密码解警报警强行进入宿舍恢复最初状态自动解警关门提示关门并报警门关且无人等待开门门关且无人解锁开门解警报警起火显示时钟扫描状态存入AT24C02设置新密码解警报警强行进入宿舍恢复最初状态自动解警关门提示关门并报警门关且无人等待开门门关且无人解锁开门解警报警起火显示时钟扫描状态2.人体监测与烟雾监测报警两模块软件设计流程图是否解警启动声光报警是否火灾发生或盗窃现象扫描状态开始是否解警启动声光报警是否火灾发生或盗窃现象扫描状态开始 N Y N Y3.宿舍人员进出及人数记录和无人提示锁门模块软件流程图设计开始开始宿舍内人数是否为零有无人员进入启动声光报警送入LCD显示扫描状态 宿舍内人数是否为零有无人员进入启动声光报警送入LCD显示扫描状态 N Y N4.宿舍安防记录模块软件流程图设计开始开始扫描状态扫描状态是否有报警是否有报警 N Y保存安防记录保存安防记录三、系统各模块调试1.人体监测与声光报警模块调试在红外传感器走动观察是否引起声光报警,输入解警密码,观察是否解警。烟雾检测与声光报警模块调试用烟雾收集瓶收集烟雾,然后将其放置烟雾传感器旁,观察声光报警器是否报警,输入解警密码,观察是否解警调试。宿舍人员进出及人数记录和无人提示锁门模块用挡光物体挡住红外对管来回移动观察LCD上人数的加减,当人数显示为0时,观察声光报警器是否报警,LCD上是否有提示锁门显示。4.密码解警模块调试根据系统方案论证及系统硬件设计中的第五模块的对键盘的描述,对键盘进行操作,并观察当输入密码解警时,密码解警是否工作。宿舍安防记录模块调试系统使系统产生报警,解开键盘后按下E键,观察是否记录了安防情况。6.其他模块调试打开电源,观察LCD是否显示时间,证实DS1302是否工作。修改密码后关闭电源,然后重新打开,输入已修改的密码解警,检验被改后的密码是否已经存入AT24C02。四、总结本系统主要采用AT89C52单片机来实现,完成了题目的一些基本要求,并且还增加了一些附加功能,证实了方案的可行性和实用性,同时,也证实了AT89C52单片机功能的优越性。但是还是有很多地方有待改进,比如说4x4矩阵键盘过于复杂,给我们编程带来不少麻烦。从选题到确定题目方案,我们团队都经历了很多讨论,这次比赛不仅锻炼了我们的动手能力,而且增强了我们的团队合作意识。在比赛过程中,我们遇到了很多困难,也曾想过放弃,但是最终还是坚持了,这次比赛培养了我们面对挫折勇于克服的意志品质和吃苦耐劳的精神。我们也深深体会到了理论结合实际的重要性,并让我们感到自己知识的匮乏,激发起我们对知识的渴望。五、参考文献1.单片机应用系统设计基础—基于C51的proteus仿真/张齐,朱宁西编著.—2版.—北京:电子工业出版社,2009.12.单片机C语言应用100例/王东锋,王会良,董冠强编著.—北京:电子工业出版社,2009.3(百例成才系列丛书)3.单片机原理及应用教程/刘瑞新等编著.—北京:机械工业出版社,2005六、附件1.附件一:程序源代码(有详细的注释)#include<reg52.h>#include<intrins.h>#include<absacc.h>#definebusy0x80#defineucharunsignedchar#defineunitunsignedint#define UNLOCK_WARNING10 // 解警A#define SET_TIME11 //设时 B#define SET_PASSWORD12 // 设密码C#define UNLOCK_OPEN_DOOR13 // 解锁开门 D#defineGET_RECORD14//E#define CLOSE_DOOR_WARNING 1 // 关门报警#define FIRE_WARNING 2 // 起火报警sbitLCM_RW=P3^4;//定义LCD引脚sbitLCM_RS=P3^5;sbitLCM_E=P3^3;sbitDOOR=P0^0; //记录门的状态sbitFIRE=P0^1; // 是否起火sbitMAN=P0^2; // 是否有人lucharCOUNT=0;//记录人数的变量sbitINPUT=P0^3; //键盘开关ucharOPEN_DOOR_PERMIT=0;//开门永许标志ucharUNLOCK_DOOR=0; //sbitSPEAKER=P3^2; //声光报警sbitLED=P0^4;ucharwarn_mark;//报警标志ucharrecord_mark;unsignedcharnew_password1[6]="000000";//unsignedcharnew_password2[6]="000000";unsignedcharpassword[6]= {0x00,0x00,0x00,0x00,0x00,0x00};unsignedchartemp_password[6]="000000";typedefstruct{//获取并记录时间的结构体charyear; charmonth; charday;charhour;charminute;charsecond;charweek;} time;unsignedcharcodeint_asc[16]="0123456789ABCDEF";//显示码表unsignedcharLine1[16]="2010/12/25";//显示缓存第一行unsignedcharLine2[16]="22:50:46";//显示缓存的第二行#define OP_READ 0xa1 //器件地址以及读取操作,0xa1即为10100001B#define OP_WRITE0xa0 //器件地址以及写入操作,0xa1即为10100000BsbitSDA=P3^7;//将串行数据总线SDA位定义在为P3.4引脚sbitSCL=P3^6;//将串行时钟总线SDA位定义在为P3.3引脚/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/voiddelay1ms(){unsignedchari,j; for(i=0;i<10;i++) for(j=0;j<33;j++) ; }/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/voiddelaynms(unsignedcharn){unsignedchari; for(i=0;i<n;i++) delay1ms();}/***************************************************函数功能:开始数据传送***************************************************/voidstart()//开始位{ SDA=1;//SDA初始化为高电平“1” SCL=1;//开始数据传送时,要求SCL为高电平“1” _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SDA=0;//SDA的下降沿被认为是开始信号 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SCL=0;//SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递)}/***************************************************函数功能:结束数据传送***************************************************/voidstop()//停止位{ SDA=0;//SDA初始化为低电平“0” _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SCL=1;//结束数据传送时,要求SCL为高电平“1” _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SDA=1;//SDA的上升沿被认为是结束信号}/***************************************************函数功能:从AT24Cxx读取数据出口参数:x***************************************************/unsignedcharReadData()//从AT24Cxx移入数据到MCU{ unsignedchari; unsignedcharx;//储存从AT24Cxx中读出的数据 for(i=0;i<8;i++) { SCL=1;//SCL置为高电平 x<<=1;//将x中的各二进位向左移一位 x|=(unsignedchar)SDA;//将SDA上的数据通过按位“或“运算存入x中 SCL=0;//在SCL的下降沿读出数据 } return(x);//将读取的数据返回}/***************************************************函数功能:向AT24Cxx的当前地址写入数据入口参数:y(储存待写入的数据)***************************************************///在调用此数据写入函数前需首先调用开始函数start(),所以SCL=0bitWriteCurrent(unsignedchary){ unsignedchari; bitack_bit;//储存应答位 for(i=0;i<8;i++) //循环移入8个位 { SDA=(bit)(y&0x80);//通过按位“与”运算将最高位数据送到S //因为传送时高位在前,低位在后 _nop_();//等待一个机器周期 SCL=1;//在SCL的上升沿将数据写入AT24Cxx _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SCL=0;//将SCL重新置为低电平,以在SCL线形成传送数据所需的8个脉冲 y<<=1;//将y中的各二进位向左移一位 } SDA=1; //发送设备(主机)应在时钟脉冲的高电平期间(SCL=1)释放SDA线, //以让SDA线转由接收设备(AT24Cxx)控制 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 SCL=1;//根据上述规定,SCL应为高电平 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 _nop_();//等待一个机器周期 ack_bit=SDA;//接受设备(AT24Cxx)向SDA送低电平,表示已经接收到一个字节 //若送高电平,表示没有接收到,传送异常 SCL=0;//SCL为低电平时,SDA上数据才允许变化(即允许以后的数据传递) returnack_bit; //返回AT24Cxx应答位}/***************************************************函数功能:向AT24Cxx中的指定地址写入数据入口参数:add(储存指定的地址);dat(储存待写入的数据)***************************************************/voidWriteSet(unsignedcharadd,unsignedchardat)//在指定地址addr处写入数据WriteCurrent{ start();//开始数据传递 WriteCurrent(OP_WRITE);//选择要操作的AT24Cxx芯片,并告知要对其写入数据 WriteCurrent(add);//写入指定地址 WriteCurrent(dat);//向当前地址(上面指定的地址)写入数据 stop();//停止数据传递 delaynms(4); //1个字节的写入周期为1ms,最好延时1ms以上}/***************************************************函数功能:从AT24Cxx中的当前地址读取数据出口参数:x(储存读出的数据)***************************************************/unsignedcharReadCurrent(){ unsignedcharx; start();//开始数据传递 WriteCurrent(OP_READ);//选择要操作的AT24Cxx芯片,并告知要读其数据 x=ReadData();//将读取的数据存入x stop();//停止数据传递 returnx;//返回读取的数据}/***************************************************函数功能:从AT24Cxx中的指定地址读取数据入口参数:set_add出口参数:x***************************************************/unsignedcharReadSet(unsignedcharset_add)//在指定地址读取{ start();//开始数据传递 WriteCurrent(OP_WRITE);//选择要操作的AT24Cxx芯片,并告知要对其写入数据 WriteCurrent(set_add);//写入指定地址 return(ReadCurrent());//从指定地址读出数据并返回}voidwrite_password()//存密码{unsignedchari;for(i=0;i<6;i++)WriteSet(i,password[i]);}voidread_password(){//读出密码unsignedchari;for(i=0;i<6;i++)password[i]=ReadSet(i);}/************************************键盘扫描程序*************************************************************************************/// 0123456789ABCDEFcodecharcodekey_code[]={0x7E,0x7D,0x7B,0x77,0xBD,0xBB,0xB7,0xDD,0xDB,0xD7,0xBE,0xDE,0xEE,0xED,0xEB,0xE7};codecharcodeksp[]={0x7F,0xBF,0xDF,0xEF};voiddelay(){unsignedchari,j;for(i=0;i<50;i++)for(j=0;j<100;j++);}charkeypad_scan()//扫描行{charkey,i;if(INPUT){P2=0xF0;while(P2!=0xF0);//有按键按下do{if(!INPUT)break;i=0;for(i=0;i<4;i++){ P2=ksp[i]; if(P2!=ksp[i]){ delay(); key=P2; if(key!=ksp[i])return(key); }}}while(1);}}uchargotkey(){ //获取按键的值,扫描列chartemp,i;temp=keypad_scan();for(i=0;i<15;i++){if(temp==key_code[i])return(i);} return(16);}/***********************************************************************以下是DS1302芯片的操作程序************************************************************************/sbitData=P0^5;//位定义1302芯片的接口,数据输出端定义在P1.1引脚sbitSCLK=P0^6;//位定义1302芯片的接口,时钟输出端口定义在P1.1引脚sbitRST=P0^7;//位定义1302芯片的接口,复位端口定义在P1.1引脚/*****************************************************函数功能:延时若干微秒入口参数:n***************************************************/voiddelaynus(unsignedcharn){unsignedchari;for(i=0;i<n;i++);}/*****************************************************函数功能:向1302写一个字节数据入口参数:x***************************************************/voidWrite1302(unsignedchardat){unsignedchari;SCLK=0;//拉低SCLK,为脉冲上升沿写入数据做好准备delaynus(2);//稍微等待,使硬件做好准备for(i=0;i<8;i++)//连续写8个二进制位数据{ Data=dat&0x01;//取出dat的第0位数据写入1302 delaynus(2);//稍微等待,使硬件做好准备 SCLK=1;//上升沿写入数据 delaynus(2);//稍微等待,使硬件做好准备 SCLK=0;//重新拉低SCLK,形成脉冲 dat>>=1;//将dat的各数据位右移1位,准备写入下一个数据位 }}/*****************************************************函数功能:根据命令字,向1302写一个字节数据入口参数:Cmd,储存命令字;dat,储存待写的数据***************************************************/voidWriteSet1302(unsignedcharCmd,unsignedchardat){RST=0;//禁止数据传递SCLK=0;//确保写数居前SCLK被拉低 RST=1;//启动数据传输 delaynus(2);//稍微等待,使硬件做好准备 Write1302(Cmd);//写入命令字 delaynus(2); Write1302(dat);//写数据 SCLK=1;//将时钟电平置于已知状态 RST=0;//禁止数据传递}/*****************************************************函数功能:从1302读一个字节数据入口参数:x***************************************************/unsignedcharRead1302(void){unsignedchari,dat; delaynus(2);//稍微等待,使硬件做好准备 for(i=0;i<8;i++)//连续读8个二进制位数据 { dat>>=1;//将dat的各数据位右移1位,因为先读出的是字节的最低位 if(Data==1)//如果读出的数据是1 dat|=0x80;//将1取出,写在dat的最高位 SCLK=1;//将SCLK置于高电平,为下降沿读出 delaynus(2);//稍微等待 SCLK=0;//拉低SCLK,形成脉冲下降沿 delaynus(2);//稍微等待 } returndat;//将读出的数据返回}/*****************************************************函数功能:根据命令字,从1302读取一个字节数据入口参数:Cmd***************************************************/unsignedcharReadSet1302(unsignedcharCmd){unsignedchardat;RST=0;delaynus(2);//拉低RSTSCLK=0;delaynus(2);//确保写数居前SCLK被拉低RST=1;delaynus(2);//启动数据传输Write1302(Cmd);//写入命令字dat=Read1302();//读出数据SCLK=1;delaynus(2);//将时钟电平置于已知状态RST=0;//禁止数据传递returndat;//将读出的数据返回}/*****************************************************函数功能:1302进行初始化设置*************************************************/voidInit_DS1302(ucharyear,ucharmonth,ucharday,ucharhour,ucharminute,ucharsecond){ WriteSet1302(0x8E,0x00);//根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((second/10)<<4|(second%10)));//根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((minute/10)<<4|(minute%10)));//根据写分寄存器命令字,写入分的初始值 WriteSet1302(0x84,((hour/10)<<4|(hour%10)));//根据写小时寄存器命令字,写入小时的初始值 WriteSet1302(0x86,((day/10)<<4|(day%10)));//根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((month/10)<<4|(month%10)));//根据写月寄存器命令字,写入月的初始值 WriteSet1302(0x8c,((year/10)<<4|(year%10)));//根据写年寄存器命令字,写入年的初始值}/*****获取时间分别存入结构体TIME中*************************************************/timegettime(){timeget_now; unsignedcharReadValue;//储存从1302读取的数据 ReadValue=ReadSet1302(0x8d);//从年寄存器读get_now.year=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化 ReadValue=ReadSet1302(0x89);//从月寄存器读get_now.month=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化 ReadValue=ReadSet1302(0x87);//从日寄存器读get_now.day=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化 ReadValue=ReadSet1302(0x85);//从时寄存器读get_now.hour=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化ReadValue=ReadSet1302(0x83);//从分寄存器读get_now.minute=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化ReadValue=ReadSet1302(0x81);//从秒寄存器读数据get_now.second=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化 ReadValue=ReadSet1302(0x8B);//从秒寄存器读数据get_now.week=((ReadValue&0x70)>>4)*10+(ReadValue&0x0F);//将读出数据转化returnget_now;}/**********************************************************************************************/voidconvert_time(){ timenow; now=gettime(); Line1[0]=int_asc[2]; Line1[1]=int_asc[0]; Line1[2]=int_asc[now.year/10]; Line1[3]=int_asc[now.year%10]; Line1[5]=int_asc[now.month/10]; Line1[6]=int_asc[now.month%10]; Line1[8]=int_asc[now.day/10]; Line1[9]=int_asc[now.day%10]; Line2[0]=int_asc[now.hour/10]; Line2[1]=int_asc[now.hour%10]; Line2[3]=int_asc[now.minute/10]; Line2[4]=int_asc[now.minute%10]; Line2[6]=int_asc[now.second/10]; Line2[7]=int_asc[now.second%10]; Line2[8]='\0'; Line2[9]='\0'; Line2[10]='\0'; Line2[11]='\0'; Line2[12]='\0'; Line2[13]='\0'; Line2[14]='\0'; Line2[15]='\0';} /*********************************LCD1602驱动函数*******************************************************************************************/voiddelay_LCM(unitk){uniti,j; for(i=0;i<k;i++) for(j=0;j<60;j++){;}}voidtest_1602busy() { P1=0xFF; LCM_E=1; LCM_RS=0; LCM_RW=1; _nop_();while(P1&busy){ LCM_E=0; _nop_(); LCM_E=1; _nop_(); } LCM_E=0; } voidwrite_1602Command(ucharco) { test_1602busy(); LCM_RS=0; LCM_RW=0; LCM_E=0; _nop_(); P1=co; _nop_(); LCM_E=1; _nop_(); LCM_E=0; }voidwrite_1602Data(ucharData) { test_1602busy(); P1=Data; LCM_RS=1; LCM_RW=0; LCM_E=1; _nop_(); LCM_E=0; } voidinit_1602(void)//初始化1602{ write_1602Command(0x38); delay_LCM(5); write_1602Command(0x01); delay_LCM(5); write_1602Command(0x06); delay_LCM(5); write_1602Command(0x0F); delay_LCM(5);}//此方法很好voidDisplayOneChar(ucharX,ucharY,ucharDData)//锁定要显示的行和列 { Y&=1; X&=15; if(Y) X|=0x40; X|=0x80; write_1602Command(X); write_1602Data(DData); } voiddisplay_1602(uchar*DData,ucharX,ucharY)//1602显示函数 { ucharListLength=0; uchart=X;Y&=0x01;X&=0x0F; while(DData[ListLength]&&ListLength<(16-t)) { DisplayOneChar(X++,Y,DData[ListLength]); ListLength++; } while(X<16){DisplayOneChar(X++,Y,0x00);} }/*************************************获取密码并处理************************************************/ voidget_password() {//获取输入的六位密码 uchari; for(i=0;i<6;i++){ display_1602("-",i,1);temp_password[i]=gotkey();//暂存至temp_password[]display_1602("*",i,1);//输入密码后移显示* } }/********************************************************/intcheck_password()//验证输入的密码是否正确 { chari; i=0; while((temp_password[i]==password[i])&&(i<6))i++; if(i==6)return(1); elsereturn(0); }/*************************************///voidinit(){//uchari;//for(i=0;i<256;i++)WriteSet(i,0);//}/*******************当报警时记录安防**********************************/voidrecord(uchartype){uchari,j;timet;for(i=0;i<5;i++)for(j=155;j>5;j--)WriteSet(j,ReadSet(j-1));t=gettime();WriteSet(6,t.month);WriteSet(7,t.day);WriteSet(8,t.hour);WriteSet(9,t.minute);WriteSet(10,type);}/*******************读取近期三十天的安防情况********************************/voidget_record(){uchari,keys;i=6;display_1602("PRESS_KEY_E!",0,0);display_1602("TO_GET_RECORDS!",0,1);while(1){keys=gotkey();if(keys!=14)break;Line1[5]=int_asc[ReadSet(i)/10];Line1[6]=int_asc[ReadSet(i)%10];Line1[8]=int_asc[ReadSet(i+1)/10];Line1[9]=int_asc[ReadSet(i+1)%10];Line2[0]=int_asc[ReadSet(i+2)/10];Line2[1]=int_asc[ReadSet(i+2)%10];Line2[3]=int_asc[ReadSet(i+3)/10];Line2[4]=int_asc[ReadSet(i+3)%10];Line2[8]='';Line2[9]='T';Line2[10]='Y';Line2[11]='P';Line2[12]='E';Line2[13]=':';Line2[14]=int_asc[ReadSet(i+4)];display_1602(Line1,0,0);//display_1602(Line2,0,1);i=i+5;if(i>151)i=6;}}/*********************设置新的时间*************************************************/voidset_new_time(){ucharkey1,key2;timenew_time;convert_time();//获取时间并装入显示缓存数组display_1602(Line1,0,0);display_1602(Line2,0,1);//显示时钟/****************设年****************/DisplayOneChar(2,0,'_');do{key1=gotkey();}while(key1>9);DisplayOneChar(2,0,int_asc[key1]);DisplayOneChar(3,0,'_');do{key2=gotkey();}while(key2>9);DisplayOneChar(3,0,int_asc[key2]);new_time.year=key1*10+key2;/***************设月*******************/DisplayOneChar(5,0,'_');do{key1=gotkey();}while(key1>1);DisplayOneChar(5,0,int_asc[key1]);DisplayOneChar(6,0,'_');if(key1==1){do{key2=gotkey();}while(key2>9);}else{do{key2=gotkey();}while(key2>2);}DisplayOneChar(6,0,int_asc[key2]);new_time.month=key1*10+key2;/**************设日******************/DisplayOneChar(8,0,'_');do{key1=gotkey();}while(key1>3);DisplayOneChar(8,0,int_asc[key1]);DisplayOneChar(9,0,'_');if(key1<3){do{key2=gotkey();}while(key2>9);}else{do{key2=gotkey();}while(key2>1);}DisplayOneChar(9,0,int_asc[key2]);new_time.day=key1*10+key2;/******************设时**********************/DisplayOneChar(0,1,'_');do{key1=gotkey();}while(key1>2);DisplayOneChar(0,1,int_asc[key1]);DisplayOneChar(1,1,'_');if(key1==2){do{key2=gotkey();}while(key2>3);}else{do{key2=gotkey();}while(key2>9);}DisplayOneChar(1,1,int_asc[key2]);new_time.hour=key1*10+key2;/*******************设分*********************/DisplayOneChar(3,1,'_');do{key1=gotkey();}while(key1>5);DisplayOneChar(3,1,int_asc[key1]);DisplayOneChar(4,1,'_');do{key2=gotkey();}while(key2>9);DisplayOneChar(4,1,int_asc[key2]);new_time.minute=key1*10+key2;/********************设秒********************/DisplayOneChar(6,1,'_');do{key1=gotkey();}while(key1>5);DisplayOneChar(6,1,int_asc[key1]);DisplayOneChar(7,1,'_');do{key2=gotkey();}while(key2>9);DisplayOneChar(7,1,int_asc[key2]);new_time.second=key1*10+key2;//将设置的时间写入DS1302芯片Init_DS1302(new_time.year,new_time.month,new_time.day,new_time.hour,new_time.minute,new_time.second);}/******************************************************************/intset_new_password()//设置新的密码 { uchari;display_1602("IN_OLD_PASSWORD:",0,0);//首先要求输入旧的密码delay_LCM(100); get_password(); if(!check_password()){//如果输入错误则跳回0 display_1602("WRRONG!",0,0); delay_LCM(3000); return(0);} i=0; display_1602("IN_NEW_PASSWORD:",0,0);//提示输入新的密码 get_password();while(i<6){new_password1[i]=temp_password[i];i++; } i=0;display_1602("CONFIRM_AGAIN:",0,0);//再次输入新的密码delay(); get_password(); i=0;while(new_password1[i]==temp_password[i])i++;//比较两次输入的新密码 if(i==6){ for(i=0;i<6;i++)password[i]=temp_password[i];write_password(); return(1);//设置正确返回1 } elsereturn(0); }/*****************************人数记录函数********************************************************///ucharcount(){////Line2[12]=int_asc[COUNT/10];// Line2[13]=int_asc[COUNT%10];//}/**********************获得状态并判断是否要发出相应的报警****************************************/voidwarn(){/********************判断是否已经解警*************************************/if(warn_mark==0){SPEAKER=1;LED=1;return;}//return相当于goto,如果已经解警了,将不会在报警,要单片机复位/****************如果起火则报警**********************************/if((P0&0x02)&&warn_mark){//P0^1开为起火了关闭为无火起火且没有解过警display_1602("****FIRE!!!**",0,0); display_1602("FIRE_IN_THE_HOLE",0,1);//LCD提示起火了SPEAKER=0;//LED=0;if(record_mark){record(1);record_mark=0;}//记录报警}/***************************当不解锁解警开门非法进入报警***********************************/if(warn_mark==1&&OPEN_DOOR_PERMIT==0&&((MAN==1)||(DOOR==1))){//如果没有解锁开门此时开门永许没有开而进入//但里面有人为翻窗而入//或者强行把门打开while(1){//强行非法入室或开门设死循环报警display_1602("PUTUP_YOUR_HANDS",0,0); display_1602("**STOP_STELING!!",0,1);SPEAKER=0;//报警LED=0;if(record_mark){record(2);record_mark=0;}if(INPUT){//内部特殊解警解除死循环使恢复正常display_1602("INPUT_PASSWORD:",0,0);display_1602("UNLOCK_WARNING!",0,1);//提示解警delay_LCM(2000); get_password(); if(check_password()){//获取密码成功SPEAKER=1;LED=1;//关闭报警
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 1988年离婚协议书
- 中小学生新守则课件
- 2025地铁设备安装施工单位合同执行与考评评分细则
- 电子商务电子签名法合同
- 2025年上海市房屋买卖合同范本
- 2025年个人汽车买卖合同范本
- 2025小麦的购销合同范文
- 护理人员继续教育制度
- 高中数学 322函数模型的应用举例教案 新人教版必修
- 慢性宫颈炎的预防和护理
- 2025-2030全球智能工厂MOM解决方案行业调研及趋势分析报告
- 《古巴导弹危机》课件
- (商务星球2024版)地理七年级上学期教学计划(新教材)
- 【MOOC】电路原理-东北大学 中国大学慕课MOOC答案
- 问诊课件教学课件
- 船舶维修现场安全生产应急预案
- 糖尿病足的评估
- 机动车检测站设备维护管理制度
- 2《永遇乐-京口北固亭怀古》公开课一等奖创新教学设计统编版高中语文必修上册
- 短视频素材购买合同
- 呼吸与危重症医学专科医师规范化培训基地认定细则
评论
0/150
提交评论