毕业设计论文_基于单片机语音智能密码锁设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
一、设计任务及要求:
设计任务:
设计一个具有设置数字密码任设、存储、画面显示、语言播报以及具有报警功能的密码锁。
要求:
1.密码由六位数字组成,可以由用户自定义设置。
2.密码锁具有语言播报和状态显示功能。
3.一次性只允许三次密码输入操作,支持密码修改。
4.具有报警功能。
指导教师签名
2013年月日二、指导教师评语:
指导教师签名:
2013年月日三、成绩
验收盖章
2013年月日
目录
目录 (2)
1 设计目的 (1)
2 设计的主要内容和要求 (1)
3 整体设计方案 (1)
4硬件电路设计 (2)
4.1 系统总电路的设计 (2)
4.2 5V直流稳压电源模块 (3)
4.3 控制电路的设计 (4)
4.4 语音模块电路的设计 (4)
4.5 信号输入电路的设计 (5)
4.6 密码储存电路的设计 (6)
4.7 LCD显示电路的设计 (7)
4.8 继电器模拟锁模块及蜂鸣器报警模块 (8)
5软件程序设计 (9)
6 系统仿真 (12)
6.1 系统仿真环境及参数设置 (15)
6.2系统仿真结果及其分析 (15)
7使用说明 (20)
8 设计总结 (20)
参考文献 (21)
附件 (22)
语音智能密码锁的设计
1 设计目的
本文所设计的智能密码锁系统是以89C52为中心控制器、4*4键盘采集输入信号、用24C04芯片对设定的密码进行保存,同时设有SX6288组成的语音模块,通过LCD、LED灯以及语音模块直观的显示密码锁所处状态。
用户可以自定义设置六位的数字密码,并有三次输入密码的机会,当密码输入错误时密码锁将会发出报警声,当三次输入密码错误时,密码锁将进行键盘锁定一段时间。
2 设计的主要内容和要求
1)LCD能够及时显示密码锁的状态信息。
2)语音模块能够播报密码锁状态。
3)能够设定初始密码,支持密码修改。
4)能够快速、准确的采集键盘上的输入信息。
5)用24C04芯片进行设定密码和保存。
6)当密码输入错误时,系统自行报警,并在连续输入超过三次密码错误时,
将对键盘锁定一段时间。
7)设计一个5V的稳定电源,给系统供电。
8)系统自定义强,工作稳定、安全。
3 整体设计方案
本文设计的语音智能密码锁系统框图如图3.1所示。
系统主要分为电源模块、控制模块、语音模块、密码保存模块、LCD显示模块、模拟锁以及蜂鸣器报警模块组成。
单片机电源模块键盘模块24C04密码存
储模块
语音播报模
块
LCD 显示模块
模拟锁
报警模块
图3.1 智能密码锁系统框图 本系统分为写初始密码和密码锁工作两部分。
1) 写密码部分:开始时LCD 显示初始化状态,进键盘扫描,当按下C 键后,
可以自定义设定六位的密码,当按下D 键时,LCD 显示所设密码。
2) 密码锁工作部部分:开始时LCD 显示初始状态,锁处于关的状态,红色LED
亮,等待键盘扫描。
按下A 键后,蜂鸣器响三声,LCD 显示请输入密码提示进
入开锁进程,此时有三次输入密码机会。
若输入密码正确,将有蜂鸣器将会响四
声,LCD 显示锁已打开,红色LED 灭、绿色LED 亮四种方式提示成功开锁,
此时,锁处于已开锁状态。
之后若按下E 键系统将会进入初始状态;如果此时按
下B 键,系统将会进入重设密码进程,可以自定义重设六位的数字密码,设定
后按下E 键,系统进入初始状态。
若输入密码错误,蜂鸣器将会发出报警声,连
续三次输入错误密码,系统将会对键盘锁定一段时间,按下E 键后,系统进入读
密码初始状态。
4硬件电路设计
4.1 系统总电路的设计
本系统原理图如图4.1所示:
图4.1 系统电路原理图
在设计本系统硬件时,主要有以下电路模块:
1)+5V直流稳压电源模块;
2)系统硬件将采用AT89C52单片机为控制部分;
3)SX6288中文语音合成播报模块;
4)以4*4矩阵键盘为信号输入模块;
5)采用24C04芯片作为保存密码模块;
6)LCD显示电路模块;
7)继电器模拟锁模块及蜂鸣器报警模块。
4.2 直流稳压电源模块
系统5V直流电源图4.2电路供电,它的工作过程如下:220V市电经过变压器降压为9V,经电容滤波变为平滑的10.8V电压,最后经过7805三端稳压器电路降压,再滤波最终得到5V的直流电源。
从而保证芯片在正常电压范围内工作,
保证了整个电路的正常工作。
图4.2 直流稳压电源电路原理图
4.3 控制电路的设计
本设计系统采用AT89C52单片机作为总控制电路,如图4.3所示。
本单片机具有40个引脚,6个中断源,20个I/O接口。
本设计以P0以及P2、P3端口作为信号输出口,P1端口作为信号采集输入口,通过C语言编程对其进行控制,本设计利用其集成度高,体积小,开发性能好,控制能力强,可靠性强的特点使智能密码锁工作稳定安全。
图4.3单片机电路图
4.4 语音模块电路的设计
本语音模块包括:控制模块、SX6288A语音合成芯片、数据库芯片spiflash、功放模块和喇叭。
主控制器和SX6288A之间通过UART接口连接,控制器通过通
讯接口SX6288A发送控制命令和文本,SX6288A把接收到的文本转化为语音信号输出,输出的信号经过功率放大器进行放大后接到喇叭进行播放。
SX6288A具有音质好、自然度高、使用方法简单、合成速度快、价格低等特点,支持GB2312、GBK、BIG5和UNICODE内码格式的文本,支持多种通讯波特率。
实物图如图4.4所示:
图4.4 语音模块实物图
从左至右引脚名称和说明如下:
SP+:0.5W8欧姆的扬声器正级。
SP- :0.5W8欧姆的扬声器正级。
BUSY:语音处理忙信号,忙为高电平,不忙为低电平。
TX:模块的串行数据发送端,连接单片机P3.0 RXD引脚。
RX:模块的串行数据接收端,连接单片机P3.1 TXD引脚。
GND:电源地GND。
VCC;电源直流电3.3-5V。
4.5 信号输入电路的设计
本设计利用4*4矩阵键盘作为信号电路,其电路图如图4.5所示:
图4.5 4*4键盘信号输入电路的设计
单片机通过对4*4键盘扫描,采集输入指令,从而使单片机完成相应数据处理。
4*4矩阵键盘工作原理如下:4*4矩阵键盘采用逐行扫描法,依次从第一至最末行线上发出低电平信号, 如果该行线所连接的键没有按下的话, 则列线所接的端口得到的是全“1”信号, 如果有键按下的话, 则得到非全“1”信号。
然后再通过从列线读入的信号来识别是哪一列的按键闭合。
为了防止双键多多键同时按下,再以同样的方法往下扫描,一直到最后一行,若发现仅有一个“1”,则为有效键,否则全部作废。
本设计以P1^0-P^3为行扫描信号,在通过P1^4-P^7作为列线读入。
对各个按键进行相应功能的设置,单片机对有效键时的信号采集,进而对采集的信号进行处理。
4.6 密码储存电路的设计
本设计采用AT24C04芯片作为密码保存模块电路,其引脚图如4.6.1所示。
AT24C04是典型的I2C总线结构,具有512bit容量EEPROM存储器,其是一种采用I2C总线接口的串行总线存储器,这类存储器具有体积小、引脚少、功耗低、工作电压范围宽等特点。
其具有支持I2C总线协议、占用单片机I/O端口少,芯片扩展方便、读写简单等优点。
密码储存电路如图4.6.2所示:
图4.6.1 AT24C04引脚图
图4.6.2 密码储存电路
工作原理:AT24C04传送数据过程中共有三种类型信号:开始信号、停止信号和应答信号。
开始信号:SCL保持高电平的状态下,SDA出现下降沿。
出现开始信号以后,总线被认为“忙”。
停止信号:SCL保持高电平的状态下,SDA出现上升沿。
停止信号过后,总线被认为“空闲”。
应答信号:接收数据的器件在接收到8位数据后,向发送数据的器件发出特定的低电平脉冲,表示已收到数据。
主器件产生开始信号以后,发送的第一个字节为控制字节。
前七位为从器件的地址片选信号。
最低位为数据传送方向位(高电平表示读从器件,低电平表示写从器件),然后发送一个选择从器件片内地址的字节,来决定开始读写数据的起始地址。
接着再发送数据字节,可以是单字节数据,也可以是一组数据,由主器件来决定。
从器件每接收到一个字节以后,都要返回一个应答信号(ASK=0)。
主器件在应答时钟周期高电平期间释放SDA线,转由从器件控制,从器件在这个时钟周期的高电平期间必须拉低SDA线,并使之为稳定的低电平,作为有效的应答信号。
在本设计中通过单片机P3.4和P3.5引脚分别对AT24C04芯片SCL和SDA引脚控制,实行密码数据的读和写,从而完成密码的设定保存。
4.7 LCD显示电路的设计
本设计采用1602液晶作为显示电路,可以进行背光对比度调节,内含复位电路,提供了各种控制命令,如:清屏、字符闪烁、光标闪烁、显示移位等多种功能,有80字节显示数据存储器DDRAM内建有160个5X7点阵的字型的字符发生器CGROM8个可由用户自定义的5X7的字符发生器CGRAM。
其电路图如图4.7所示。
在本系统中,单片机P0端口作为LCD数据接收口,P2.0-P2.2控制液晶的读写和使能端,完成对液晶的显示控制。
图4.7 LCD显示电路
4.8 继电器模拟锁模块及蜂鸣器报警模块
在本设计系统中用继电器断开与闭合模拟锁的开锁与锁定的状态,继电器一个端口接在单片机P3.6,当P3.6为高电平时,继电器绕线电流通过三极管Q2放大,绕线产生磁效应,吸合衔铁,视为开锁,其电路图如图4.8.1所示。
在报警模块中,通过一个三极管放大电流从而完成蜂鸣器的驱动,当P3.7端口为高电平时,蜂鸣器发出响声,低电平时不响。
本设计通过对电平频率的控制从而实现不同的响声。
其电路图如4.8.2所示。
图4.8.1 模拟锁电路图
图4.8.2 报警电路
5软件程序设计
5.1 系统程序设计
本系统程序分为两部分,初始写密码程序和密码锁工作程序。
如图所示图5.1为写初始密码流程图,图5.2为密码工作流程图。
图5.1 初始密码程序设定流程图
密码输入
初始化画面显示
键盘扫描
按键C 是
否按下
Y 键盘扫描
显示设置密码
开始
结束
按键D 是否按下
Y
N
N
开始
系统初始化信息提示
报警、语音播报
开锁状态信息提示
判断密码是否正
确
NO
YES 密码输入、语音提示
是否重设密码
键盘扫描
输入密码、语音提示
NO
YES
闭锁
图5.2 密码锁工作主程序流程图
1)写初始密码部分:LCD显示初始化状态,系统进入键盘扫描,仅当C键按下后,系统进入密码设定阶段,其他键对系统不产生作用,进入设定阶段后,可以自定义设定六位的密码。
继续对键盘扫描,当按下D键时,LCD显示所设密码,按下C键可以重设密码,按下其他键是将不会对系统产生影响。
其设计流程图如图5.1所示。
2)密码锁工作部分产生:LCD显示初始状态,系统进入键盘扫描。
仅当按下A 键后,蜂鸣器响三声,LCD显示请输入密码提示进入开锁进程,此时有三次输入密码机会。
若密码输入正确,蜂鸣器响四声,LCD显示锁已打开,红色LED 灭、绿色LED亮,若按下E键系统将会进入初始状态;如果此时按下B键,系统将会进入重设密码进程,可以自定义重设六位的数字密码,设定后按下E键,系统进入初始状态。
若输入密码错误,蜂鸣器将会发出报警声,连续三次输入错误密码,系统将会对键盘锁定一段时间,按下E键后,系统进入读密码初始状态。
其流程图如图5.2所示。
5.2 主要程序设计
1)初始密码设定
在程序中包含蜂鸣器驱动子函数、延时子函数、4*4键盘扫描函数、开机液晶显示子函数、写密码子函数、读密码子函数、1602驱动子头文件函数、AT24C04驱动头文件函数(见附件)。
其主函数如下所示:
void main()
{
uchar i;
BEEP=0;
start: Delay_ms(10);
lcd_init();
I2C_init();
lcd_wcmd(0x00|0x80);
i = 0;
while(line1_data[i] != '\0')
{
lcd_wdat(line1_data[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(line2_data[i] != '\0')
{
lcd_wdat(line2_data[i]);
i++;
}
while(1)
{
P1=0xf0;
if(P1!=0xf0)
{
MatrixKey();
if(key==0x0c)WriteCode();
if(key==0x0d)ReadCode();
if(key==0x0e)goto start;
}
}
}
2)密码锁工作函数
在程序中包含蜂鸣器驱动子函数、延时子函数、4*4键盘扫描函数、开机液晶显示子函数、写密码子函数、读密码子函数、密码输入错误显示子函数、密码输入正确显示子函数、重设密码子函数、报警鸣声子函数、定时中断子函数、1602驱动子头文件函数、AT24C04驱动头文件函数(见附件)。
其主函数如下所示:
void main()
{
TMOD=0x21;//定时器0 方式1 定时器1 工作在方式2
TH0=0xee; //5ms 定时初值
TL0=0x00;
EA=1; //开总中断
ET0=1;//打开定时器0
SCON = 0x50; //串口工作方式为1 ,串行允许接收
TR1 = 1; //允许定时器1工作
TH1 = 0xfd; //波特率9600bps fosc="11".0592MHz
TL1 = 0xfd;
ES = 1; //开串口中断
Delay_ms(10);
lcd_init(); //液晶初始化
I2C_init(); //I2C初始化
START: RELAY=1;//继电器关闭
lcd_clr(); //调入清屏函数
StartDisp();//开机画面显示
read_nbyte (0xa0,0x00,code_buf,6); //从24Cxx的0x00开始的单元中读出6个密码存入code_buf[]数组中
P1=0xf0;
while(P1==0xf0);//等待按键按下
SCAN: MatrixKey();//键盘扫描
if(key!=0x0a)goto SCAN; //若按下的不是A键,跳转到标号SCAN处继续扫描
//Uart_SendString(shuru); //语音播报密码错误
TR0=1; //启动定时器
Delay_ms(500);
beep();
if(flag_2s==1)flag_2s=0;//若2s到,则将2s标志位清0
else goto SCAN; //若2s到,则将2s标志位清0
PassIn(); //调用密码输入函数
while(1)
{
if(flag_comp==1)
{
MatrixKey();//键盘扫描
if(key==0x0b)//若有B按下进入密码重设
{
PassSet(); //调入密码设置函数
MatrixKey();
if(key==0x0e)goto START; //若按下了E键,则跳转到标志START处重新开始}
if(key==0x0e)goto START;//若按下了E键,则跳转到标志START处重新开始}
if(flag_comp==0)
{
MatrixKey();
if(key==0x0e)goto START; //若按下了E键,则跳转到标志START处重新开始}
}
}
/**********定时中断****************/
void timer0() interrupt 1
{
TH0=0xee;TL0=0x00;
count_5ms++;
if(count_5ms==200)
{
count_5ms=0;
sec++;
}
if(sec==2)
{
flag_2s=1;
TR0=0;
}
}
6 系统仿真
6.1 系统仿真环境及参数设置
本设计在Protues的ISIS 7.0SP2或者更高版本的软件环境下打开电路仿真图,接下来将设计好的程序在Keil C51 μVision3开发集成环境上编译成机器语言,生成.hex文件。
打开Proteus软件,进入ProteusISIS,首先将设置初始密码程序的hex文件导入到80C52中,点击按钮,按下C键选择密码设置,D键为读密码功能。
再把密码锁工作程序生成的hex导入单片机中,E键位功能复位键,按下A键系统进入密码输入状态,输入密码后,按下B键后系统进入密码重设状态。
6.2系统仿真结果及其分析
6.2.1系统仿真
系统整体仿真电路图如图6.1所示:
图6.1 密码锁整体proteus仿真图
6.2.2设定初始密码仿真
导入初始密码hex文件后,系统进入初始化状态,仿真结果如图6.2所示。
按下扫描按键C,系统进入密码设定输入状态,LCD上提示输入密码,仿真结
果如图6.3所示。
图6.3 设定初始密码输入仿真图
设定密码后按下D键,系统进入读密码状态,LCD上显示所设密码,仿真图如图6.4所示。
图6.4 设定初始密码读密码仿真图
6.2.3 密码锁工作仿真
导入密码锁工作hex文件后,系统进入初始状态,仿真图同图6.1所示。
按下A键,系统进入输入密码状态,LCD提示请输入密码,仿真图如图6.5所示。
图6.5密码锁工作输入密码仿真图
输入正确密码时,LCD提示密码输入成功,锁打开,绿色LED灯亮,仿真图
如图6.6所示。
按下E键,系统初始状态,仿真图同图6.1所示。
若连续三次输入密码错误,LCD提示密码输入,仿真图如图6.7所示。
图 6.7 连续三次密码输入错误仿真图
图6.8 重设密码输入仿真图
图6.9重设密码成功仿真图
输入密码正确后,按下B键,系统进入重设密码状态,LCD提示请输入密码,仿真图如图6.8所示,密码重设成功如图6.9所示。
7使用说明
使用本设计宜按以下步骤进行:首先加载设定初始密码hex文件,按下C 键,进入密码设定输入状态,设定密码后按下D键读取自己所设密码;再加载密码锁工作hex文件,进入密码锁工作状态,按下A键,输入所设密码,输入密码正确后,按下B键可以自定义重设密码,按下E键进入初始状态。
8 设计总结
本设计以89C52为中心控制器、用4*4键盘采集输入信号、采用典型的I2C 总线结构AT24C04芯片储存密码、并且通过LCD显示屏和LED灯直观地显示各密码锁各种状态,用继电器模拟锁的状态,用户可以自定义设置6位的数字密码,系统还具有报警功能,该系统基本能够实现本文能够提出的功能和要求。
本设计也存在不足,缺陷一,单重的密码锁不能满足较高的安全需要。
缺陷二,该系统对电的依赖比较大,必须使24C04一直保持供电状态,当断电后不
能正常工作。
缺点三,在按键按下时,按键声不够响亮清晰,在仿真时显得反映
比较慢,假如能采用语音模块,能用语音播报按键时密码所处状态,密码锁将会更具人性化。
通过这次对智能密码锁的设计,感受更多的是自己的能力有限,知识不够丰富,知识点掌握的不够扎实,使得自己不能按自己初始设想完成自己的设计,使得所设的密码锁不够完整。
在这次设计中还让,让我了解了实时控制的原理,懂得怎样合理的使用芯片,发挥其功能。
体会到做设计时必须有条理的按一定步骤实行系统的设计、各个步骤的实施。
总之,这次课程设计使在电路设计方面受益匪浅。
参考文献
[1] 林立.张俊亮.曹旭东.刘得军.单片机原理及应用: 基于Proteus和Keil C [M].北京:
电子工业出版社, 2009:2-5.
[2] 郑锋.王巧芝.李英建.刘瑞国.51单片机应用系统典型模块开发大全 [M].北京:中国铁道出版社,2011:5-20.
[3] 张俊谟.单片机中级教程[M].北京:北京航空航天大学出版,2000:36-45.
[4] 单片机高级语言C51 Windows环境编程与应用[M],电子工业出版社,2001:86-95.
[5] AT89C51 DATA SHEEP[M] .Philips Semiconductors,1999:15-36.
[6] 康华光.电子技术基础(第5版)[M].北京:高等教育出版社,2006:45-48.
[7] 彭华林等编.数字电子技术[M].长沙:湖南大学出版社,2004:45-60.
[8] 金唯香等编.电子测试技术[M].长沙:湖南大学出版社,2004:26-30.
附件
AT24C04头文件 "I2C_drive.h"
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit SDA = P3^4;
sbit SCL = P3^3;
bit ack;
void delayNOP();
void I2C_start();
void I2C_stop();
void I2C_init();
void I2C_Ack();
void I2C_NAck();
uchar RecByte();
uchar SendByte(uchar write_data) ;
uchar read_nbyte (uchar SLA,uchar SUBA,uchar *pdat,uchar n); uchar write_nbyte(uchar SLA,uchar SUBA,uchar *pdat,uchar n); void delayNOP()
{
_nop_();_nop_();
_nop_();_nop_();
}
void I2C_start()
{
SDA = 1;
SCL = 1;
delayNOP();
SDA = 0;
delayNOP();
SCL = 0;
}
void I2C_stop() {
SDA = 0;
SCL = 1; delayNOP();
SDA = 1; delayNOP();
SCL = 0;
}
void I2C_init() {
SCL = 0;
I2C_stop();
}
void I2C_Ack() {
SDA = 0;
SCL = 1; delayNOP();
SCL = 0;
SDA = 1;
}
void I2C_NAck() {
SDA = 1;
SCL = 1; delayNOP();
SDA = 0;
}
uchar RecByte()
{
uchar i,read_data;
read_data=0x00;
SDA=1;
for(i = 0; i < 8; i++)
{
SCL = 1;
read_data <<= 1;
read_data |= SDA;
delayNOP();
SCL = 0;
delayNOP();
}
SCL = 0;
delayNOP();
return(read_data);
}
uchar SendByte(uchar write_data) {
uchar i;
for(i = 0; i < 8; i++)
{
SDA = (bit)(write_data & 0x80); _nop_();
_nop_();
delayNOP();
SCL = 0;
write_data <<= 1;
}
delayNOP();
SDA = 1;
SCL = 1;
delayNOP();
if(SDA==1) ack=0;
else ack=1;
SCL = 0;
delayNOP();
return ack;
}
uchar write_nbyte(uchar SLA,uchar SUBA,uchar *pdat,uchar n) {
uchar s;
I2C_start();
SendByte(SLA);
if(ack==0) return(0);
SendByte(SUBA);
if(ack==0) return(0);
for(s=0; s<n; s++)
{
SendByte(*pdat);
if(ack==0) return(0);
pdat++;
}
I2C_stop();
return(1);
}
uchar read_nbyte (uchar SLA,uchar SUBA,uchar *pdat,uchar n) {
uchar s;
I2C_start();
SendByte(SLA);
if(ack==0) return(0);
SendByte(SUBA);
if(ack==0) return(0);
I2C_start();
SendByte(SLA+1);
if(ack==0) return(0);
for(s=0; s<n; s++)
{
*pdat=RecByte();
I2C_Ack();
pdat++;
}
I2C_NAck();
I2C_stop();
return(1);
}
1602头文件 "LCD_drive.h"
#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit LCD_RS=P2^0;
sbit LCD_RW=P2^1 ;
sbit LCD_EN=P2^2;
void Delay_ms(uint xms) ; bit lcd_busy();
void lcd_wcmd(uchar cmd); void lcd_wdat(uchar dat) ; void lcd_clr() ;
void lcd_init() ;
void Delay_ms(uint xms) {
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
bit lcd_busy()
{
bit result;
LCD_RS = 0;
LCD_RW = 1;
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
result = (bit)(P0&0x80); LCD_EN = 0;
return result;
}
void lcd_wcmd(uchar cmd) {
while(lcd_busy());
LCD_RS = 0;
LCD_RW = 0;
LCD_EN = 0;
_nop_();
_nop_();
P0 = cmd;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
void lcd_wdat(uchar dat) {
while(lcd_busy());
LCD_RS = 1;
LCD_RW = 0;
LCD_EN = 0;
P0 = dat;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 1;
_nop_();
_nop_();
_nop_();
_nop_();
LCD_EN = 0;
}
void lcd_clr() {
lcd_wcmd(0x01); Delay_ms(5);
}
void lcd_init() {
Delay_ms(15); lcd_wcmd(0x38); Delay_ms(5); lcd_wcmd(0x38); Delay_ms(5); lcd_wcmd(0x38); Delay_ms(5);
lcd_wcmd(0x0c); Delay_ms(5); lcd_wcmd(0x06);
Delay_ms(5);
lcd_wcmd(0x01);
Delay_ms(5);
}
设定初始密码程序
#include <reg51.h>
#include "I2C_drive.h"
#include "LCD_drive.h"
#define uchar unsigned char
#define uint unsigned int
uchar code_buf[6]={1,2,3,4,5,6}; uchar key;
uchar temp;
sbit BEEP=P3^7;
void beep()
{
BEEP=0;
Delay_ms(100);
BEEP=1;
Delay_ms(100);
}
void MatrixKey()
{
P1=0xff;
P1=0xef;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xee:key=0;break; case 0xed:key=1;break; case 0xeb:key=2;break; case 0xe7:key=3;break; }
temp=P1;
beep();
temp=temp & 0x0f; while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
P1=0xdf;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xde:key=4;break; case 0xdd:key=5;break; case 0xdb:key=6;break; case 0xd7:key=7;break; }
temp=P1;
beep();
temp=temp & 0x0f; while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
P1=0xbf;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xbe:key=8;break; case 0xbd:key=9;break; case 0xbb:key=10;break; case 0xb7:key=11;break; }
temp=P1;
beep();
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
P1=0x7f;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0x7e:key=12;break;
case 0x7d:key=13;break;
case 0x7b:key=14;break;
case 0x77:key=15;break;
}
temp=P1;
beep();
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
}
uchar code line1_data[] = {" WRITE & READ "}; uchar code line2_data[] = {" ---PASSWORD--- "}; uchar code W_line1_data[] = {" WRITE CODE "}; uchar code W_line2_data[] = { "NUM:------ "}; uchar code R_line1_data[] = {" READ CODE "}; uchar code R_line2_data[] = {"NUM:------ "}; void CodeIn()
{
static uchar lcd_x=0;
static uchar count=0;
do{
P1=0xf0;
if(P1!=0xf0)
{
MatrixKey();
if((key>=0)&&(key<=9))
{
code_buf[count]=key;
lcd_wcmd((0x44+lcd_x)|0x80);
lcd_wdat(code_buf[count] +0x30); count++;
lcd_x++;
}
}
}while(count<6);
if(count>=6){count=0;lcd_x=0;} }
void WriteCode()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(W_line1_data[i] != '\0') {
lcd_wdat(W_line1_data[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(W_line2_data[i] != '\0')
{
lcd_wdat(W_line2_data[i]);
i++;
}
CodeIn();
write_nbyte(0xa0,0x00,code_buf,6); }
void ReadCode()
{
uchar i,j;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(R_line1_data[i] != '\0')
{
lcd_wdat(R_line1_data[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(R_line2_data[i] != '\0')
{
lcd_wdat(R_line2_data[i]);
i++;
}
read_nbyte (0xa0 ,0x00,code_buf,6); for(j=0;j<6;j++)
lcd_wcmd((0x44+j)|0x80);
lcd_wdat(code_buf[j]+0x30); }
}
void main()
{
uchar i;
BEEP=0;
start: Delay_ms(10);
lcd_init();
I2C_init();
lcd_wcmd(0x00|0x80);
i = 0;
while(line1_data[i] != '\0') {
lcd_wdat(line1_data[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(line2_data[i] != '\0') {
lcd_wdat(line2_data[i]);
i++;
}
while(1)
{
P1=0xf0;
if(P1!=0xf0)
MatrixKey();
if(key==0x0c)WriteCode();
if(key==0x0d)ReadCode();
if(key==0x0e)goto start;
}
}
}
密码锁工作程序
#include <reg52.h>
#include <string.h>
#include "I2C_drive.h"
#include "LCD_drive.h"
#define uchar unsigned char
#define uint unsigned int
uchar code_buf[6];
uchar incode_buf[6];
uchar key;
uchar temp;
sbit BEEP=P3^7;//蜂鸣器
sbit RELAY=P3^6;//继电器
uchar count_5ms,sec;
bit flag_2s=0;
bit flag_comp=0;
const uchar shuru[]="<G> 请输入密码。
";//输入密码语音提示
const uchar eshuru[]="<G> 密码错误,请重新输入密码。
"; //重新输入密码const uchar rshuru[]="<G>\x12 "; //重新输入密码
const uchar chongse[]="<G> 请输入新密码。
"; //重新设定密码
//const uchar suoding[]="<G> 请稍后再试。
";//三次后锁定
void beep() // 蜂鸣器响声
{
BEEP=0;
Delay_ms(300);
BEEP=1;
Delay_ms(300);
}
/*********串口发送一个字节************/
/*void Uart_SendChar(unsigned char dat)
{
SBUF = dat; //待发送的数据写入缓冲区
while(!TI); //等待发送完成
TI = 0; //清零发送标志位
} */
/********串口发送一个字符串函数****************/ void Uart_SendString( uchar *trdata)
{
uchar i=0;
while(trdata[i]!=0x00)
{
SBUF=trdata[i];
while(!TI);
TI=0;
i++;
}
}
void MatrixKey()//矩阵键盘扫描
{
P1=0xef;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xee:key=0;break; case 0xed:key=1;break; case 0xeb:key=2;break; case 0xe7:key=3;break; }
temp=P1;
beep();
temp=temp & 0x0f; while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xde:key=4;break; case 0xdd:key=5;break; case 0xdb:key=6;break; case 0xd7:key=7;break; }
temp=P1;
beep();
temp=temp & 0x0f; while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
P1=0xbf;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0xbe:key=8;break; case 0xbd:key=9;break; case 0xbb:key=10;break; case 0xb7:key=11;break; }
temp=P1;
beep();
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
P1=0xff;
P1=0x7f;
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
Delay_ms(10);
temp=P1;
temp=temp & 0x0f;
if (temp!=0x0f)
{
temp=P1;
switch(temp)
{
case 0x7e:key=12;break;
case 0x7d:key=13;break;
case 0x7b:key=14;break;
case 0x77:key=15;break;
}
temp=P1;
beep();
temp=temp & 0x0f;
while(temp!=0x0f)
{
temp=P1;
temp=temp & 0x0f;
}
}
}
}
/************开机显示画面*******************/ uchar code line1_data[] = {" KEY LOCK "}; uchar code line2_data[] = {" MADE IN TANNING "};
/************密码输入画面*******************/ uchar code in_line1[] = {" PLEASE INPUT "}; uchar code in_line2[] = {"PASSWORD:------ "};
/************密码输入正确画面*******************/ uchar code inok_line1[] = {"INPUT PASSWORD "}; uchar code inok_line2[] = {" INOPUT OK "}; /************密码输入错误画面*******************/ uchar code inerr_line1[] = {"INPUT PASSWORD "}; uchar code inerr_line2[] = {" INPUT ERR "}; /************修改密码画面*******************/ uchar code modify_line1[] = {"MODIFY PASSWORD "}; uchar code modify_line2[] = {"PASSWORD:------ "}; /************密码修改成功画面*******************/ uchar code setok_line1[] = {"MODIFY PASSWORD "}; uchar code setok_line2[] = {" MODIFY OK "}; /********以下是开机画面显示函数********/
void StartDisp()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(line1_data[i] != '\0')
{
lcd_wdat(line1_data[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(line2_data[i] != '\0')
{
lcd_wdat(line2_data[i]);
i++;
}
}
/********以下是密码输入画面显示函数********/ void CodeInDisp()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(in_line1[i] != '\0')
{
lcd_wdat(in_line1[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(in_line2[i] != '\0')
{
lcd_wdat(in_line2[i]);
i++;
}
}
/********以下是密码输入错误显示函数********/ void CodeInErr()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(inerr_line1[i] != '\0')
{
lcd_wdat(inerr_line1[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(inerr_line2[i] != '\0')
{
lcd_wdat(inerr_line2[i]);
i++;
}
}
/********以下是密码输入正确显示函数********/ void CodeInOk()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(inok_line1[i] != '\0')
{
lcd_wdat(inok_line1[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(inok_line2[i] != '\0')
{
lcd_wdat(inok_line2[i]);
i++;
}
}
/********以下是密码设置画面显示函数********/ void CodeSetDisp()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(modify_line1[i] != '\0')
{
lcd_wdat(modify_line1[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(modify_line2[i] != '\0')
{
lcd_wdat(modify_line2[i]);
i++;
}
}
/********以下是密码设置成功画面显示函数********/ void CodeSetOk()
{
uchar i;
lcd_clr();
lcd_wcmd(0x00|0x80);
i = 0;
while(setok_line1[i] != '\0')
{
lcd_wdat(setok_line1[i]);
i++;
}
lcd_wcmd(0x40|0x80);
i = 0;
while(setok_line2[i] != '\0')
{
lcd_wdat(setok_line2[i]);
i++;
}
}
void PassIn()
{
static uchar lcd_x=0; //显示指针,注意是静态局部变量static uchar count=0; //密码计数器,注意是静态局部变量static uchar code_n=0; //密码输入次数
PASSWORD: lcd_clr(); //清屏
RELAY=1 ;//闭锁
CodeInDisp(); //密码输入画面
do{
P1=0xf0;
if(P1!=0xf0)//若有按键按下
{
MatrixKey();//键盘扫描
P1=0xf0;。