仿真原理图如下(proteus仿真工程文件可到本帖附件中下载)
3.6 开锁机构
在基于单片机的电子密码锁设计中,用户需要输入密码,密码正确则发出开锁信号开锁。
在这次基于单片机的电子密码锁设计中,通过控制蜂鸣器的发音来指示系统的开锁功能。蜂鸣器是一种采用直流电压供电的电子讯响器。图3-9是用蜂鸣器指示的开锁机构仿真图。因为在设计中是以蜂鸣器发生来指示开锁是否成功,当密码输入正确时蜂鸣器响起来,代表锁开了。
图3-9开锁机构指示电路
3.7 报警机构
在这次基于单片机的电子密码锁设计中,通过控制报警显示LED来指示系统的报警功能。图3-10是用基于LED的报警机构仿真图。控制RELAY输出高低电平,即P3.4引脚,就可以控制报警显示LED的亮灭,从而指示相关信息。
图3-10报警机构模拟仿真图
当用户输入密码错误次数达到预设警告次数时,系统调用报警子程序,使LED亮起来,同时禁止键盘输入。
3.8 硬件综合设计
根据电路原理,在PROTEUS中画出各功能模块的仿真图,各个功能模块验证正确后,将所有模块集合到一个电路设计图中,画出具有所有功能的总体硬件仿真图。
待程序编写好后,将KEIL和PROTEUS联调,观察此电路设计图可以知道各个功能模块和器件的工作情况。届时,根据实际情况可以适当修改电路图或者程序,以达到设计的目的。
单片机源程序如下:
- #include<reg51.h> //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义
- #include"lcd1602.h"
- #include"i2c.h"
- sbit LED=P3^3; //继电器控制引脚
- sbit RELAY=P3^4; //继电器控制引脚
- sbit BUZZER=P3^5; //蜂鸣器控制引脚
- sbit SET=P0^7; //设置
- sbit LCK=P0^6; //关锁
- #define LOCK_TIME_second 10
- #define SU 1/256
- #define GPIO_KEY P1 //4X4矩阵键盘输入
- unsigned char KeyValue; //用来存放读取到的键值
- unsigned char saved_Value[4]={6,7,6,7}; //初始密码
- unsigned char input_Value[4];
- unsigned char Right_flg=0,Right_flg0=0;
- unsigned char set_flg=0,LOCK_flg=0;
- unsigned char temp00;
- unsigned int time_cnt,time_remember,delay_ddll;
- long int DECvalue=0;
- //存储芯片存储的内容
- /*===============================================
- 地址: 0 1 2 3 4 5 6
- 数据:无 密码 密码 密码 密码 无 错误次数
- =================================================*/
- void TimerConfiguration(void); //定时中断
- void KeyDown(); //检测按键函数
- void At24c02Write(unsigned char addr,unsigned char dat);
- unsigned char At24c02Read(unsigned char addr);
- //====主函数入口======
- void main()
- {
- char i=0,j=0;
- //unsigned char aa;
- char k=0;
- LcdInit(); //液晶初始化
- clear_window();
- TimerConfiguration(); //初始化定时器
- Lcd1602_Delay1ms(5);
- At24c02Write(1,6); //初始化存储芯片,实际电路中就不需要
- At24c02Write(2,7);
- At24c02Write(3,6);
- At24c02Write(4,7);
- At24c02Write(6,0); ////清除错误输入次数
- RELAY=1;
- BUZZER=1;
- while(1)
- {
- KeyDown(); ////按键扫描
- ///===========正常输入密码操作======================
- if (KeyValue<=9 && !set_flg && !LOCK_flg) //有按键按下
- {
- input_Value[i]=KeyValue;
- if (Right_flg0)
- { clear_window();
- Right_flg0=0;
- }
- LcdWriteCom(0x80+i); //显示当前按键的值
- LcdWriteData('*');
- i++;
- if(i>=4) //判断
- {
- Right_flg0=0;
- for (j=0;j<4;j++)
- {
- if (input_Value[j]!=saved_Value[j])
- Right_flg0=1;
- }
- clear_window();
- if(!Right_flg0) ////密码输入正确
- {
- BUZZER=0; //声音报警
- delay_ddll = 1;
- LcdWriteCom(0x80+i+2);
- LcdWriteData('O');
- LcdWriteData('K');
- At24c02Write(6,0); ////清除错误输入次数
- }
- else
- {
- BUZZER=1;
- LcdWriteCom(0x80+i+2);
- LcdWriteData('E');
- LcdWriteData('R');
- temp00=At24c02Read(6); ////存储输入错误次数
- if (temp00>=2) //连续输入错误超过3次
- {
- LOCK_flg=1;
- RELAY=0; /////指示灯起来
- LcdWriteCom(0x80+i+2);
- LcdWriteData('L');
- LcdWriteData('K');
- }
- At24c02Write(6,temp00+1);
- }
- i=0;
- }
- }
- ///===========正常输入密码操作 end======================
- ///===========修改密码操作======================
- if (KeyValue<=9 && set_flg && !LOCK_flg) //有按键按下 KeyValue!=66
- {
- input_Value[k]=KeyValue;
-
- LcdWriteCom(0x80+k); //显示当前按键的值
- LcdWriteData('*');
- k++;
- if(k>=4) //判断
- {
- if (set_flg==2)
- {
- for (j=0;j<4;j++)
- {
- saved_Value[j]=input_Value[j];
- At24c02Write(j+1,saved_Value[j]);
- }
- clear_window();
- set_flg=0;
- LED = 0; //设置状态指示灯亮起来
- delay_ddll =1;
- // LcdWriteCom(0x80+k+2);
- // LcdWriteData('O');
- // LcdWriteData('K');
- }
- if (set_flg==1)
- {///============================================
- Right_flg=0;
- for (j=0;j<4;j++)
- {
- if(input_Value[j]!=saved_Value[j])
- Right_flg=1;
- }
- clear_window();
- if(!Right_flg) ///旧密码输入正确
- {
- set_flg=2; ///可以进行下一步操作
- LcdWriteCom(0x80+0x40); //
- LcdWriteData('N');
- LcdWriteData('E');
- LcdWriteData('W');
- }
- else
- {
- LcdWriteCom(0x80+k+2);
- LcdWriteData('E');
- LcdWriteData('R');
-
- temp00=At24c02Read(6); ////存储输入错误次数
- if (temp00>=2)
- {
- LOCK_flg=1;
- RELAY=0; /////指示灯起来
- LcdWriteCom(0x80+i+2);
- LcdWriteData('L');
- LcdWriteData('K');
- }
- At24c02Write(6,temp00+1);
- }
- } ///============================================
-
- k=0;
- }
- }
- ///===========修改密码操作 end======================
- if (KeyValue==0x0A && !LOCK_flg) //有按键按下
- {
- clear_window();
- set_flg=1;
- LcdWriteCom(0x80+0x40); //
- LcdWriteData('O');
- LcdWriteData('L');
- LcdWriteData('D');
- k=0; //=================
- }
- ////=============############================================
- else if (KeyValue==0x0B && !LOCK_flg) //有按键按下,关上锁,清除窗口!LCK
- {
- BUZZER=1;
- clear_window();
- }
-
- if (delay_ddll)
- {
- delay_ddll++;
- if (delay_ddll>2000)
- {
- LED = 1;
- BUZZER = 1;
- delay_ddll = 0;
- }
- }
- ////=============================================
- Lcd1602_Delay1ms(1);
- }
- }
- /*******************************************************************************
- * 函 数 名 : KeyDown
- * 函数功能 : 检测有按键按下并读取键值
- * 输 入 : 无
- * 输 出 : 无
- *******************************************************************************/
- void KeyDown(void)
- {
- unsigned char a=0;
-
- KeyValue=66;
- GPIO_KEY=0x0f;
- if(GPIO_KEY!=0x0f)//读取按键是否按下
- {
- Lcd1602_Delay1ms(10); //延时10ms进行消抖
- if(GPIO_KEY!=0x0f) //再次检测键盘是否按下
- {
- //测试列
- GPIO_KEY=0X0F;
- switch(GPIO_KEY)
- {
- case(0X07): KeyValue=0;break;
- case(0X0b): KeyValue=1;break;
- case(0X0d): KeyValue=2;break;
- case(0X0e): KeyValue=3;break;
- }
- //测试行
- GPIO_KEY=0XF0;
- switch(GPIO_KEY)
- {
- case(0X70): KeyValue=KeyValue;break;
- case(0Xb0): KeyValue=KeyValue+4;break;
- case(0Xd0): KeyValue=KeyValue+8;break;
- case(0Xe0): KeyValue=KeyValue+12;break;
- }
- while((a<250)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
- {
- Lcd1602_Delay1ms(2);
- a++;
- }
- }
- }
- }
- /*******************************************************************************
- * 函数名 : void At24c02Write(unsigned char addr,unsigned char dat)
- * 函数功能 : 往24c02的一个地址写入一个数据
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- void At24c02Write(unsigned char addr,unsigned char dat)
- {
- I2cStart();
- I2cSendByte(0xa0);//发送写器件地址
- I2cSendByte(addr);//发送要写入内存地址
- I2cSendByte(dat); //发送数据
- I2cStop();
- }
- /*******************************************************************************
- * 函数名 : unsigned char At24c02Read(unsigned char addr)
- * 函数功能 : 读取24c02的一个地址的一个数据
- * 输入 : 无
- * 输出 : 无
- *******************************************************************************/
- unsigned char At24c02Read(unsigned char addr)
- {
- unsigned char num;
- I2cStart();
- I2cSendByte(0xa0); //发送写器件地址
- I2cSendByte(addr); //发送要读取的地址
- I2cStart();
- ……………………
- …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码
所有资料51hei提供下载:
仿真代码.7z
(398.91 KB, 下载次数: 2351)
演示视频.7z
(9.91 MB, 下载次数: 255)
|