用24C04与1602LCD设计电子密码锁完全代码
基于单片机的LCD1602智能门锁设计

基于单片机的LCD1602智能门锁设计
简介
智能门锁是一种新型安全门锁,与传统的机械锁相比,具有便捷、高效、安全等特点。
我们基于单片机设计了一种智能门锁,采用LCD1602显示屏幕,能够在门锁上显示密码、时间、日期等信息,方便用户使用。
系统架构
我们的智能门锁设计采用了以下系统架构:
- 单片机主控模块
- 电子密码模块
- LCD1602显示屏模块
- 电源控制模块
- 电驱动模块
主要功能
我们的智能门锁具有以下主要功能:
1. 输入密码解锁。
2. 后台管理员管理,包括增删管理员、更改密码等功能。
3. LCD1602显示屏幕,显示日期、时间、密码等信息。
4. 低功耗设计,长时间使用。
5. 安装简单方便,适用于不同类型的门。
设计优点
我们的智能门锁相比其他门锁设计,具有以下优点:
1. 性能稳定、安全、可靠。
2. 使用方便,普通用户和管理员均可操作。
3. 采用可扩展模块设计,可随时升级扩充。
4. 低功耗设计,长时间使用不必频繁更换电池。
结束语
我们的智能门锁基于单片机设计,具有高效、安全等特点,能够为用户提供安全便捷的门锁体验。
该门锁的设计优点突出,性能稳定,值得用户信赖。
毕业设计——密码锁电路程序

密码锁本设计以STC89C52RC单片机为核心,利用AT24C02存储密码,做到掉电存储密码的电子密码锁。
电路:程序:#include<reg52.h>#include<intrins.h>#define uint unsigned int#define uchar unsigned char#define N 7#define OP_READ 0xa1 // 器件地址以及读取操作#define OP_WRITE 0xa0 // 器件地址以及写入操作#define MAX_ADDR 0x7f // AT24C02最大地址sbit SCL=P2^0;sbit SDA=P2^1;sbit CSH=P3^0;sbit e=P3^4;sbit rs=P3^5;sbit sp=P3^6;sbit lock=P3^1;sfr duan=0x80;sfr key=0x90;uint ci;uchar kc,sc,sc2;int shu1,shu2,jh,jg;uchar code table[] =" LOCK "; uchar code table2[]="WELLCOME TO USE!"; uchar code table3[]="PASS WORD:";uchar code table4[]="ERRO!";uchar code table5[]="OPEN!";uchar code table6[]="NEW PASS WORD"; uchar code table7[]="SUCCESSFUL!";uchar code table8[]="FAIL!";uchar code cmm[6]={1,2,3,3,2,1};uchar mm[6];uchar tablesuan[N];void init();void writec(uint com);void writed(uint dat);void delay(uint shu);uchar keyscan();void xieshuzu(uchar a[],uchar add);void shuru();void kaiji();void bijiao();void xies(uchar a,uchar add);void delayms(unsigned char ms);void gmm();/***********************//***********************//***********************/void start()// 开始位{SDA = 1;SCL = 1;_nop_();_nop_();SDA = 0;_nop_();_nop_();_nop_();_nop_();SCL = 0;}void stop()// 停止位{SDA = 0;_nop_();_nop_();SCL = 1;_nop_();_nop_();_nop_();_nop_();SDA = 1;}unsigned char shin()// 从AT24Cxx移入数据到MCU{unsigned char i,read_data;for(i = 0; i < 8; i++){SCL = 1;read_data <<= 1;read_data |= (unsigned char)SDA;SCL = 0;}return(read_data);}bit shout(unsigned char write_data)// 从MCU移出数据到A T24Cxx{unsigned char i;bit ack_bit;for(i = 0; i < 8; i++) // 循环移入8个位{SDA = (bit)(write_data & 0x80);_nop_();SCL = 1;_nop_();_nop_();SCL = 0;write_data <<= 1;}SDA = 1; // 读取应答_nop_();_nop_();SCL = 1;_nop_();_nop_();_nop_();_nop_();ack_bit = SDA;SCL = 0;return ack_bit; // 返回A T24Cxx应答位}void write_byte(unsigned char addr, unsigned char write_data) // 在指定地址addr处写入数据write_data{start();shout(OP_WRITE);shout(addr);shout(write_data);stop();delayms(10); // 写入周期}unsigned char read_current()// 在当前地址读取{unsigned char read_data;start();shout(OP_READ);read_data = shin();stop();return read_data;}unsigned char read_random(unsigned char random_addr)// 在指定地址读取{start();shout(OP_WRITE);shout(random_addr);return(read_current());}void delayms(unsigned char ms)// 延时子程序{unsigned char i;while(ms--){for(i = 0; i < 120; i++);}}/***********************//***********************//***********************/ //主程序/void main(){ init();kaiji();delay(1000);writec(0x01);xieshuzu(table3,0x80);if(CSH==0){write_byte(2,cmm[0]); //在24c02的地址2中写入数据secdelayms(2);write_byte(3,cmm[1]); //在24c02的地址2中写入数据sec delayms(2);write_byte(4,cmm[2]); //在24c02的地址2中写入数据sec delayms(2);write_byte(5,cmm[3]); //在24c02的地址2中写入数据sec delayms(2);write_byte(6,cmm[4]); //在24c02的地址2中写入数据sec delayms(2);write_byte(7,cmm[5]); //在24c02的地址2中写入数据sec delayms(2);}mm[0]=read_random(2);delayms(2);mm[1]=read_random(3);delayms(2);mm[2]=read_random(4);delayms(2);mm[3]=read_random(5);delayms(2);mm[4]=read_random(6);delayms(2);mm[5]=read_random(7);while(1){lock=0;shuru();bijiao();}}/***********************/ //初始化/ void init(){lock=0;writec(0x01);writec(0x38);writec(0x0c);IT0=1;EX0=1;}/***********************/ //写开机画面/ void kaiji(){xieshuzu(table,0x80);xieshuzu(table2,0xc0);}/***********************/ //写数组/ void xieshuzu(uchar a[],uchar add){uchar cis;writec(add);for(cis=0;a[cis]!='\0';cis++){writed(a[cis]);delay(2);}}/***********************/ //写数字/ void xies(uchar a,uchar add){writec(add);writed(0x30+a);}/***********************/ //写指令/ void writec(uint com){e=0;rs=0;duan=com;delay(2);e=1;delay(2);e=0;}/***********************/ //写数据/void writed(uint dat){e=0;rs=1;duan=dat;delay(2);e=1;delay(2);e=0;}/***********************/ //延时/ void delay(uint shu){uint i,j;for(i=shu;i>0;i--)for(j=110;j>0;j--);}/***********************/ //现盘扫描/ uchar keyscan(){uchar k,skey;key=0xfe;skey=key;sp=1;if(skey!=0xfe){delay(10);skey=key;if(skey!=0xfe){switch(skey){case(0xee):k=7;kc++;break;case(0xde):k=8;kc++;break;case(0xbe):k=9;kc++;break;case(0x7e):k=0x0a;kc++;break;default:break;}while(skey!=0xfe)skey=key;sp=0;return k;}}key=0xfd;skey=key;if(skey!=0xfd){delay(10);skey=key;if(skey!=0xfd){switch(skey){case(0xed):k=4;kc++;break;case(0xdd):k=5;kc++;break;case(0xbd):k=6;kc++;break;case(0x7d):k=0x0b;kc++;break;default:break;}while(skey!=0xfd)skey=key;sp=0;return k;}}key=0xfb;skey=key;if(skey!=0xfb)delay(10);skey=key;if(skey!=0xfb){switch(skey){case(0xeb):k=1;kc++;break;case(0xdb):k=2;kc++;break;case(0xbb):k=3;kc++;break;case(0x7b):k=0x0c;kc++;break;default:break;}while(skey!=0xfb)skey=key;sp=0;return k;}key=0xf7;skey=key;if(skey!=0xf7){delay(10);skey=key;if(skey!=0xf7){switch(skey){case(0xe7):k=0x0d;kc++;break;case(0xd7):k=0; kc++;break;case(0xb7):k=0x0e;kc++;break;case(0x77):k=0x0f;kc++;break;default:break;}while(skey!=0xf7)skey=key;sp=0;return k;}}}/***********************/ //输入数据处理/ void shuru(){uchar k=0,xw=0x80;sc=0;kc=0;xieshuzu(table3,0x80);do{while(kc==sc)k=keyscan();if(kc==1)writec(0x01);tablesuan[sc]=k;//xies(tablesuan[sc],xw);xies(tablesuan[sc],0xc0);writec(xw);writed(0x2A);xw++;if(sc==5)goto out;}while((tablesuan[sc++]<=9)&&(sc<N));out:;if(sc>N){writec(0x01);xieshuzu(table4,0x80);}}void bijiao(){if((tablesuan[0]==mm[0])&&(tablesuan[1]==mm[1])&&(tablesuan[2]==mm[2])&&(tablesuan[3] ==mm[3])&&(tablesuan[4]==mm[4])&&(tablesuan[5]==mm[5])){EA=1;lock=1;writec(0x01);xieshuzu(table5,0x80);delay(6500);EA=0;}else{writec(0x01);xieshuzu(table3,0x80);}}void gmm(){uchar k=0,xw=0x80;sc2=0;kc=0;xieshuzu(table6,0x80);do{while(kc==sc2)k=keyscan();if(kc==1)writec(0x01);mm[sc2]=k;xies(mm[sc2],0xc0);writec(xw);writed(0x2A);xw++;if(sc2==5)goto out2;}while((mm[sc2++]<=9)&&(sc2<N));//out:;//if(sc>N)//{writec(0x01);xieshuzu(table8,0x80);goto out3;//}out2:;writec(0x01);xieshuzu(table7,0x80);write_byte(2,mm[0]); //在24c02的地址2中写入数据secdelayms(2);write_byte(3,mm[1]); //在24c02的地址2中写入数据secdelayms(2);write_byte(4,mm[2]); //在24c02的地址2中写入数据secdelayms(2);write_byte(5,mm[3]); //在24c02的地址2中写入数据secdelayms(2);write_byte(6,mm[4]); //在24c02的地址2中写入数据secdelayms(2);write_byte(7,mm[5]); //在24c02的地址2中写入数据secdelayms(2);out3:;}void INTT0() interrupt 0{EA=0;gmm();EA=1;}。
电子密码锁C程序

cord_h=P3&0xf0;
//读入列线值
if(cord_h!=0xf0)
//先检测有无按键按下
{
delay(10);
// 去抖
if((P3&0xf0)!=0xf0)
{ cord_h=P3&0xf0;
//读入列线值
P3=cord_h|0x0f;
// 输出当前列线值
cord_l=P3&0x0f;
//读入行线值
write_data(table1[num]); delay(1); } while(1) { mima=KeyPro(); write_com(0xc4+x); write_com(0x0f); if((mima!=0xff)&&(x<6)) {
单片机密码锁C程序完整代码

单片机密码锁C程序完整代码2009-08-18 14:39#include<AT89x51.h>#include"intrins.h"#include"key.h"#include"xsh.h"#include"24c02.h"#define ulong unsigned longbit BJCB=0;//报警标志XG=0,//修改密码标志位BJ=0,//报警标志位SJ=0;//锁键盘标志位// xg=0;//修改密码标志位uchar PSWD0_0[16]={0};//密码输入缓存存储单元//uchar code PSWD0_1[16]={1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8};//用户初始密码存储单元//uchar PSWD1_0[16]={0};//读出密码缓存存储单元uchar PSWD1_1[16]={1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8};//管理员初始密码存储单元sbit OUT=P3^5;//输出端口sbit L1=P0^2;//上电指示sbit L2=P0^1;//开锁指示sbit L3=P0^0;//报警指示uint mg=0,//密码个数KSC=0,//开锁次数BJC=0,//报警次数TCNTY=0,//用户按键定时次数累加TCNTG=0,//管理员输入密码定时次数yhsh,//用户输入标志位glsh,//管理员输标志位shw;//密码输完标志位void yhmimaxig();//密码修改程序void glmimaxig();//管理员修改程序void bjyin(ulong t){ulong c;uint n;for(c=0;c<t;c++){for(n=0;n<50;n++); //延时BEEP=~BEEP; //取反输出到喇叭的信号}}void delay_10ms(void){uint i = 1000;while(i--);}//////////////定时中断服务函数////////////////////////////////////// void timer0() interrupt 1{uint i;TH0=(65536-50000)/256; //对TH0 TL0赋值50MS定时TL0=(65536-50000)%256; //重装计数初值if(yhsh==1){TCNTY++;//用户定时计数if(shw==1){TR0=0;TCNTY=0;}if(TCNTY==200){TR0=0;//关闭T0定时器TCNTY=0;mg=0;//密码个数清零L1=1;for(i=0;i<2;i++)//声光报警电路{L3=0;bjyin(1000);L3=1;delay(1000);}L1=0;}}else if(glsh==1){TCNTG++;//管理员定时计数if(shw==1){TR0=0;TCNTG=0;}if(TCNTG==160){TR0=0;//关闭T0定时器TCNTG=0;mg=0;//密码个数清零L1=1;for(i=0;i<2;i++)//声光报警电路{L3=0;bjyin(1000);L3=1;delay(1000);}L1=0;}}}void main(){uint i;TMOD=0x01; //定时器工作在方式1ET0=1;EA=1;TH0=(65536-50000)/256; //对TH0 TL0赋值TL0=(65536-50000)%256; //使定时器0.05秒中断一次//Read_page24c02(0x00,PSWD1_1,16);//向24c02里读用户初始密码 //i2cWrite24LC16B(0,0X20);/////////////第一次向24c02里写入初始管理员密码、用户密码、开锁次数/////////////////////KSC=i2cRead24LC16B(0X20);loop: L1=0;//上电红灯亮L2=1;//开锁成功后绿灯亮L3=1;//输错时黄灯亮报警OUT=0;//开信号关闭display_0(KSC);//开锁前显示///////////密码输入/////////////////if(SJ==0)//锁键盘标志位为0{do{flag=0;//键盘标志位key();if(flag==1&&num==12) //判断是否为管理员功能键按下{goto gl;}if(flag==1&&num<=9){PSWD0_0[mg]=num;mg++;//密码个数}if(flag==1&&num==14&&mg>=1)//输入错误删除{mg=mg-1;}if(mg==1) //有密码键按下开定时器限时{TR0=1;yhsh=1;}}while(num!=15);if(mg!=16){for(i=mg;i<16;i++){PSWD0_0[i]=0;}}/////////////////密码比较电路//////////////////////////// if(flag==1&&num==15){ flag=0;yhsh=0;shw=1;num=0;for(i=0;i<16;i++) //从24c02里读出16个密码{PSWD1_1[i]=i2cRead24LC16B(i);delay_10ms;}for(i=0;i<16;i++){if(PSWD1_1[i]!=PSWD0_0[i]){BJCB=1;break;}else}}if(BJCB!=0){BJC++;if(BJC!=3){BJCB=0; //第一次和第二次报警delay(500);mg=0;//密码个数清零L1=1;for(i=0;i<3;i++)//声光报警电路{L3=0;display_3();bjyin(1000);L3=1;delay(1000);}goto loop;}else if(BJC==3){BJC=0;BJCB=0;display_5();//三次输入密码失败,自锁SJ=1;//锁键盘标志位mg=0;//密码个数清零L1=1;for(i=0;i<2;i++)//声光报警电路{L3=0;bjyin(1000);L3=1;delay(1000);}goto loop;}}elseif(BJCB==0){display_1(KSC);i2cWrite24LC16B(KSC,0X20);if(KSC==100){SJ=1;}L2=0;L1=1;OUT=1;mg=0;//密码个数清零loop1:do //键盘扫描等待功能键按下{flag=0;key();if(flag){flag=0;switch(num){case 13:{display_2();do{flag=0;//键盘标志位key();if(flag==1&&num<=9){PSWD0_0[mg]=num;mg++;//密码个数}if(flag==1&&num==14&&mg>=1)//输入错误删除{mg=mg-1;}if(mg==16){do //键盘扫描等待功能键按下{flag=0;key();}while(num!=15);}}while(num!=15);if(mg!=16&&num==15){for(i=mg;i<16;i++){PSWD0_0[i]=0;}}if(flag==1&&num==15){flag=0;mg=0;for(i=0;i<16;i++) //用一次写一个向24c02里写{i2cWrite24LC16B(PSWD0_0[i],i);delay_10ms;}display_1(KSC);do //键盘扫描等待功能键按下{flag=0;key();}while(num!=11); //按下返回键,锁锁返回{goto loop;}}};break;case 11: {goto loop;//break;}}}}while(flag!=0);//如果设置密码键按下goto loop1;// i2cWrite24c02_page(0x00,PSWD1_1,mg);}}else{do{flag=0;key();}while(num!=12);//判断是否为管理员功能键按下gl:do//管理员输入密码{flag=0;key();if(flag==1&&num<=9){PSWD0_0[mg]=num;mg++;//密码个数}if(flag==1&&num==14&&mg>=1)//删除键按下{mg=mg-1;}if(mg==1){TR0=1;}//开定时器TO限5秒开锁}while(num!=15);if(mg!=16&&num==15){for(i=mg;i<16;i++){PSWD0_0[i]=0;}}//////////管理员密码比较/////////////////////// //Read_page24c02(0x10,PSWD0_1,16)for(i=0;i<16;i++) //从24c02里读出16个密码{PSWD1_1[i]=i2cRead24LC16B((0x10+i));delay_10ms;}if(flag==1&&num==15){ flag=0;shw=1;num=0;for(i=0;i<mg;i++){if(PSWD1_1[i]!=PSWD0_0[i]){ BJCB=1;break;}elseBJCB=0;}}if(BJCB!=0){BJC++;if(BJC!=3){BJCB=0; //第一次和第二次报警mg=0;//密码个数清零L1=1;for(i=0;i<2;i++)//声光报警电路{L3=0;display_3();bjyin(1000);L3=1;delay(1000);}display_1(KSC);goto loop;}else{BJCB=0;display_5();//三次输入密码失败,自锁mg=0;//密码个数清零delay(10000);display_1(KSC);goto loop;}}else{SJ=0;display_4();//管理员开锁显示mg=0;L2=0;L1=1;L3=0;//密码个数清零do //键盘扫描等待功能键按下{flag=0;key();}while(flag==0); //如果设置密码键按下if(flag==1&&num==13){flag=0;display_2();do{flag=0;//键盘标志位key();if(flag==1&&num<=9){PSWD0_0[mg]=num;mg++;//密码个数}if(flag==1&&num==14&&mg>=1)//输入错误删除 {mg=mg-1;}if(mg==16){do //键盘扫描等待功能键按下{flag=0;key();}while(num!=15);}}while(num!=15);if(mg!=16&&num==15){for(i=mg;i<16;i++){PSWD0_0[i]=0;}}if(flag==1&&num==15){flag=0;mg=0;for(i=0;i<16;i++) //用一次写一个向24c02里写{i2cWrite24LC16B(PSWD0_0[i],(0x10+i));delay_10ms;}display_4();do //键盘扫描等待功能键按下{flag=0;key();}while(num!=11); //按下返回键,锁锁返回{goto loop;}}}if(flag==1&&num==10){KSC=0;i2cWrite24LC16B(KSC,0X20);display_1(KSC);do //键盘扫描等待功能键按下{flag=0;key();}while(num!=11);//按下返回键,锁锁返回goto loop;}if(flag==1&&num==11)//按下返回键,锁锁返回{goto loop;}}}}#ifndef _key_h#define _key_h#include<AT89x51.h>#define uchar unsigned char#define uint unsigned intbit flag=0;//按键按下标志位sbit BEEP=P3^7;//蜂鸣器端口delay(int z)//延时1ms{ int x,y;for (x=z;x>0;x--)for (y=140;y>0;y--);}uchar num;//按键返回值////////按键音程序////////////////// void yin(){int c,n;if(flag==1){for(c=0;c<80;c++){for(n=0;n<50;n++); //延时BEEP=~BEEP; //取反输出到喇叭的信号}}}////////////键盘程序/////////////////// int key(){ uchar temp;P2=0X7f;temp=P2&0x0f;if(temp!=0x0f){delay(5);if(temp!=0x0f){temp=P2;switch(temp){ case 0x77:num=0;break;case 0x7b:num=1;break;case 0x7d:num=2;break;case 0x7e:num=3;}do{ //等待按键抬起 temp=P2;temp=temp&0x0f;}while(temp!=0x0f);flag=1;yin();}}P2=0Xbf;temp=P2&0x0f;if(temp!=0x0f){delay(5);if(temp!=0x0f){temp=P2;switch(temp){ case 0xb7:num=4;break;case 0xbb:num=5;break;case 0xbd:num=6;break;case 0xbe:num=7;break;}do{temp=P2;temp=temp&0x0f;}while(temp!=0x0f);flag=1;yin();}}P2=0Xdf;temp=P2&0x0f;if(temp!=0x0f){delay(5);if(temp!=0x0f){temp=P2;switch(temp){ case 0xd7:num=8;case 0xdb:num=9;break;case 0xdd:num=10;break;case 0xde:num=11;break;}do{temp=P2;temp=temp&0x0f;}while(temp!=0x0f);flag=1;yin();}}P2=0Xef;temp=P2&0x0f;if(temp!=0x0f){delay(5);if(temp!=0x0f){temp=P2;switch(temp){ case 0xe7:num=12;break;case 0xeb:num=13;break;case 0xed:num=14;break;case 0xee:num=15;break;}do{temp=P2;temp=temp&0x0f;}while(temp!=0x0f);flag=1;yin();}}return(num);}#endif#ifndef _xsh_h#define _xsh_h#include<AT89x51.h>#define uchar unsigned char#define uint unsigned intsbit shj=P1^0;//串口数据口sbit sck=P1^1;//串口时钟uchar code tab[20]={ 0x88,/*0*/0xBE,/*1*/0xC4,/*2*/0x94,/*3*/0xB2,/*4*/0x91,/*5*/0x81,/*6*/0xBC,/*7*/0x80,/*8*/0x90,/*9*/0xA0,/*A*/0x83,/*b*/0xC9,/*C*/0x86,/*d*/0xC1,/*E*/0xE1,/*F*/0xA8,/*N*/0xF7,/*-*/0x94,/*反E*/0xE0/*P*/ }; //共阳数码管uchar code sb0[3]={8,8,8},/*开锁后显示*/code sb1[3]={0,15,15},/*开锁前显示*/code sb2[6]={17,17,17,17,17,17},/*修改显示*/code sb3[6]={16,0,16,0,16,0},/*第一二次报警显示*/ code sb4[6]={8,8,8,8,8,8},/*管理员进入显示*/code sb5[6]={18,18,18,18,18,18};/*第三次报警显示*///////////////////////////*显示电路*///////////////////////// void writedata(uchar num)//传送一个字节{uchar temp;int i;temp=tab[num];for(i=0;i<8;i++){ temp=temp<<1;shj=CY;sck=0;sck=1;}}void display_0(uchar temp)//开锁前状态{ int i,g,s,q;uchar m;q=temp/100;s=temp%100/10;g=temp%10;for(i=0;i<3;i++){m=sb1[i];writedata(m);}writedata(q);writedata(s);writedata(g);}void display_1(uchar temp)//开锁后状态{int i,g,s,q;uchar m;q=temp/100;s=temp%100/10;g=temp%10;for(i=0;i<3;i++){m=sb0[i];writedata(m);}writedata(q);writedata(s);writedata(g);}void display_2()//修改密码显示{int i;uchar m;for(i=0;i<6;i++){m=sb2[i];writedata(m);}}void display_3()//报警显示{int i;uchar m;for(i=0;i<6;i++){m=sb3[i];writedata(m);}}void display_4()//管理员模式显示{int i;uchar m;for(i=0;i<6;i++){m=sb4[i];writedata(m);}}void display_5()//管理员模式显示{int i;uchar m;for(i=0;i<6;i++){m=sb5[i];writedata(m);}}#endif#ifndef _24c02_h#define _24c02_h#include<AT89x51.h>#define WriteDeviceAddress 0xa0#define ReadDeviceAddress 0xa1sbit SDA=P1^5;//I2C数据端sbit SCL=P1^6;//I2C时钟端///////////////////////24C0224C08读写驱动程序///////////////////////void DelayMs(unsigned int number) {unsigned char temp;for(;number>=1;number--){for(temp=112;temp>=1;temp--) ;}}void i2cStart(void){SDA=1;SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();SDA=0;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=0;}void i2cStop(void){SDA=0;SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();SDA=1;_nop_();_nop_();_nop_();_nop_();_nop_();}void i2cAck(void){SDA=0;SCL=1;_nop_();_nop_();_nop_();_nop_();SDA=1;SCL=0;}void i2cNoAck(void){SDA=1;SCL=1;_nop_();_nop_();_nop_();_nop_();SDA=0;SCL=0;}void i2cWrite8Bit(unsigned char input) {unsigned char temp;for(temp=8;temp!=0;temp--){SDA=(bit)(input&0x80);SCL=1;_nop_();_nop_();_nop_();_nop_();_nop_();SCL=0;input=input<<1;}DelayMs(20);}unsigned char i2cRead8Bit(void){unsigned char temp,rbyte=0;for(temp=8;temp!=0;temp--){SCL=1;_nop_();_nop_();_nop_();rbyte=rbyte<<1;rbyte=rbyte|((unsigned char)(SDA));SCL=0;}return(rbyte);}void i2cWrite24LC16B(unsigned char wdata,unsigned char RomAddress) {i2cStart();i2cWrite8Bit(WriteDeviceAddress);i2cAck();i2cWrite8Bit(RomAddress);i2cAck();i2cWrite8Bit(wdata);i2cAck();i2cStop();DelayMs(20);}//写入多个字节到24c02中//传入参数:地址、待写入的数据的首地址、数据长度bit i2cWrite24c02_page(uchar RomAddress,uchar *WRdata,uchar length) {uint i;i2cStart();i2cWrite8Bit(WriteDeviceAddress);i2cAck();i2cWrite8Bit(RomAddress);i2cAck();for(i=0;i<length;i++){i2cWrite8Bit(*WRdata);i2cAck();WRdata++;}i2cStop();DelayMs(20);return(1);}unsigned char i2cRead24LC16B(unsigned char RomAddress){unsigned char x;i2cStart();i2cWrite8Bit(WriteDeviceAddress);i2cAck();i2cWrite8Bit(RomAddress);i2cAck();i2cStart();i2cWrite8Bit(ReadDeviceAddress);i2cAck();_nop_();_nop_();_nop_();x=0;x=i2cRead8Bit();i2cNoAck();i2cStop();return(x);}//从24c02中读出多个字节bit Read_page24c02(uchar RomAddress,uchar p[],uint n) { uint i;i2cStart();i2cWrite8Bit(WriteDeviceAddress);i2cAck();i2cWrite8Bit(RomAddress);i2cAck();i2cStart();i2cWrite8Bit(ReadDeviceAddress);i2cAck();_nop_();_nop_();_nop_();for(i=0;i<n-1;i++){p[i]=i2cRead8Bit();i2cAck();}p[n-1]=i2cRead8Bit();i2cNoAck();i2cStop();return(1);}。
14位数字密码锁两种设计方案

设计方案系统设计方案利用所学的电子技术知识和电子设计方法,设计出一个电子密码锁有以下两种基本方案可以选择:方案一:利用数字逻辑电路,运用各种门电路,计数器,触发器,锁存器,编/译码器等数字逻辑器件实现电子控制。
从而实现想要设计的电子密码锁的功能。
此方法设计简单,但硬件电路比较多,操作起来比较复杂。
方案二:使用MCS-51系列单片机为核心控制附加一些简单的外围电路,利用单片机的一个I/O端口组成4×4键盘作为输入电路,采用汇编语言编写程序来实现电子密码锁的各项功能,程序语言功能强大,调试较为简单。
具有很强的实用性。
设计方案选择综上提出的两种方案,方案一给出的采用数字逻辑电路的设计方法的好处就是设计简单,因为采用数字逻辑电路可以分成各个功能模块来设计,每个模块实现各自的一个功能。
这钟方法设计的密码锁电路大致包含:按键输入、密码核对、密码修改、开锁电路、错误提示电路等功能模块。
采用数字电路虽然设计简单但是操作繁琐,要运用很多数字逻辑器件,硬件电路复杂,而且可能会出现较多器件故障,同时难以检查和维护。
方案二提出的使用单片机为核心控制的方案,利用单片机丰富的I/O端口和灵活的编程设计,不但能实现密码锁的功能,而且控制准确性高,外围电路少硬件电路简单,方便灵活,调试简单不易出错,体积小成本低也利于现实中实现,具有较高的实际意义和实用价值。
这个设计方案的最关键的地方就在于编程,利用程序的执行来实现密码锁的基本功能,因此单片机方案还有较大活动空间,能在很大程度上扩展功能,方便对系统进行升级。
针对第一种方案:系统vhdl设计功能描述:假设设计的密码锁有7个数据输入键,分别用K1到K7表示;一个“确认键”(按一下确认键,密码锁内部就产生一个正脉冲),用CLK_AFFIRM表示;一个“重置和修改密码使能键”,用S/W 表示;一个开锁状态指示灯GREENLED;一个密码输入错误报警器REDLED.1.密码预置。
m16基于AT24C02的密码锁(1602)

//rs----PD4//rw----PD5//en----PD6//data---PORTB//SDA---PC1//SCL---PC0//beep--PA6//开锁---PB7//开锁状态----PB5//如果把uchar const initpassword[6]={0,0,0,0,0,0};改为_flash uchar initpassword[6]={0,0,0,0,0,0}; //则出现这错误found `unsigned' expecting `;'可我没找到错误在哪???#include <iom16v.h>#include<macros.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#define uchar unsigned char#define uint unsigned int#define w 6 //定义密码位数uchar operation=0; //操作标志位uchar pass=0; //密码正确标志uchar ReInputEn=0; //重置输入充许标志uchar s3_keydown=0; //3秒按键标志位uchar key_disable=0; //锁定键盘标志uchar countt0,second; //t1中断计数器,秒计数器//void Delay5Ms(void);uchar InputData[6]; //输入密码暂存区uchar CurrentPassword[6]={1,3,1,4,2,0}; //当前密码值uchar TempPassword[6];uchar N=0; //密码输入位数记数uchar ErrorCont; //错误次数计数uchar CorrectCont; //正确输入计数uchar ReInputCont; //重新输入计数#pragma data:codeuchar const a[]={0xFE,0xFD,0xFB,0xF7}; //控盘扫描控制表uchar const start_line[] = {"password: "};uchar const name[] = {"===Coded Lock==="}; //显示名称uchar const Correct[] = {" correct "}; //输入正确uchar const Error[] = {" error "}; //输入错误uchar const codepass[] = {" pass "};uchar const LockOpen[] = {" open "}; //OPENuchar const SetNew[] = {"SetNewWordEnable"};uchar const Input[] = {"input: "}; //INPUTuchar const ResetOK[] = {"ResetPasswordOK "};uchar const initword[] = {"Init password..."};uchar const Er_try[] = {"error,try again!"};uchar const again[] = {"input again "};uchar const initpassword[6]={0,0,0,0,0,0};/************************************************************************************************* **/void port_init(){DDRA|=BIT(6);PORTA|=BIT(6);DDRB=0xFF;PORTB=0xFF;DDRC=0xFF;PORTC=0xFF;}/***********************************************************************************************/ void segg()//关数码显示管函数{DDRA|=BIT(PA3); //PA3设置为输出状态DDRA|=BIT(PA4); //PA4设置为输出状态DDRB=0xff; //PB口设置为输出状态PORTB=0xff; //发送模码PORTA|=BIT(PA3); //PA3输出高电平,DU拉高PORTA&=~BIT(PA3); //PA3输出低电平,DU拉低,段选锁存PORTB=0xff; //发送为选关掉数码管显示PORTA|=BIT(PA4); //PA4输出高电平,WE拉高PORTA&=~BIT(PA4); //PA4输出低电平,WE拉低,位选锁存DDRA|=BIT(PA2); //PA2设置为输出状态用于LED流水灯控制IO口PORTA&=~BIT(PA2); //PA2输出低电平,DU拉低,段选LED流水灯锁存}/****************************************5ms延时*************************************/void Delay5Ms(void){uint TempCyc = 5552;while(TempCyc--);}/****************************************400ms延时*************************************/void Delay400Ms(void){uchar TempCycA = 5;uint TempCycB;while(TempCycA--){TempCycB=7269;while(TempCycB--);}}/****************************************24C02****************************************/void mDelay(uint t) //延时{uchar i;while(t--){for(i=0;i<125;i++){;}}}/*******************************************************************************************/ void Nop(void) //空操作{_nop_();_nop_();_nop_();_nop_();}/*****************************************起始条件*****************************************/ void Start(void){//Sda=1;PORTC|=BIT(1);////Scl=1;PORTC|=BIT(0);//Nop();//Sda=0;PORTC&=~BIT(1);//Nop();}/*****************************************停止条件*****************************************/ void Stop(void){//Sda=0;PORTC&=~BIT(1);////Scl=1;PORTC|=BIT(0);//Nop();//Sda=1;PORTC|=BIT(1);//Nop();}/*****************************************应答位*****************************************/ void Ack(void){//Sda=0;PORTC&=~BIT(1);//Nop();//Scl=1;PORTC|=BIT(0);//Nop();//Scl=0;PORTC&=~BIT(0);//}/*****************************************反向应答位*****************************************/ void NoAck(void){//Sda=1;PORTC|=BIT(1);//Nop();//Scl=1;PORTC|=BIT(0);//Nop();//Scl=0;PORTC&=~BIT(0);//}/****************************发送数据子程序,Data为要求发送的数据***********************/ void Send(uchar Data){uchar BitCounter=8;uchar temp;do{temp=Data;//Scl=0;PORTC&=~BIT(0);//Nop();if((temp&0x80)==0x80)//Sda=1;PORTC|=BIT(1);else//Sda=0;PORTC&=~BIT(1);////Scl=1;PORTC|=BIT(0);//temp=Data<<1;Data=temp;BitCounter--;}while(BitCounter);//Scl=0;PORTC&=~BIT(0);//}/********************读一字节的数据,并返回该字节值************************************/ uchar Read(void){uchar temp=0;uchar temp1=0;uchar BitCounter=8;//Sda=1;PORTC|=BIT(1);//do{//Scl=0;PORTC&=~BIT(0);//Nop();//Scl=1;PORTC|=BIT(0);//Nop();//if(Sda)if(PORTC&0xF2)/////////////temp=temp|0x01;elsetemp=temp&0xfe;if(BitCounter-1){temp1=temp<<1;temp=temp1;}BitCounter--;}while(BitCounter);return(temp);}/****************************************************************************************/ void WrToROM(uchar Data[],uchar Address,uchar Num){uchar i;uchar *PData;PData=Data;for(i=0;i<Num;i++){Start();Send(0xa0);Ack();Send(Address+i);Ack();Send(*(PData+i));Ack();Stop();mDelay(20);}}/********************************************************************************/void RdFromROM(uchar Data[],uchar Address,uchar Num){uchar i;uchar *PData;PData=Data;for(i=0;i<Num;i++){Start();Send(0xa0);Ack();Send(Address+i);Ack();Start();Send(0xa1);Ack();*(PData+i)=Read();//Scl=0;PORTC&=~BIT(0);NoAck();Stop();}}//**********************************LCD1602*********************************************//#define yi 0x80 //LCD第一行的初始位置,因为LCD1602字符地址首位D7恒定为1(100000000=80)#define er 0x80+0x40 //LCD第二行初始位置(因为第二行第一个字符位置地址是0x40)//*********************************************************************************************// void delay(uint xms)//延时函数,有参函数{uint x,y;for(x=xms;x>0;x--)for(y=110;y>0;y--);}/**********************************写指令****************************************/ write_1602com(uchar com)//****液晶写入指令函数****{PORTD&=~BIT(4);////数据/指令选择置为指令PORTD&=~BIT(5);////读写选择置为写PORTB=com;//送入数据delay(1);PORTD|=BIT(6);//拉高使能端,为制造有效的下降沿做准备delay(1);PORTD&=~BIT(6);//en由高变低,产生下降沿,液晶执行命令}/**********************写数据*****************************************************/ write_1602dat(uchar dat)//***液晶写入数据函数****{PORTD|=BIT(4);//////数据/指令选择置为数据PORTD&=~BIT(5);////读写选择置为写PORTB=dat;//送入数据delay(1);PORTD|=BIT(6);////en置高电平,为制造下降沿做准备delay(1);PORTD&=~BIT(6);////en由高变低,产生下降沿,液晶执行命令}/************************************初始化***************************************/ void lcd_init(void){write_1602com(0x38);//设置液晶工作模式,意思:16*2行显示,5*7点阵,8位数据write_1602com(0x0c);//开显示不显示光标write_1602com(0x06);//整屏不移动,光标自动右移write_1602com(0x01);//清显示}/*******************************************将按键值编码为数值*************************/ uchar coding(uchar m){uchar k;switch(m){case (0x18): k=1;break;case (0x28): k=2;break;case (0x48): k=3;break;case (0x88): k='A';break;case (0x14): k=4;break;case (0x24): k=5;break;case (0x44): k=6;break;case (0x84): k='B';break;case (0x12): k=7;break;case (0x22): k=8;break;case (0x42): k=9;break;case (0x82): k='C';break;case (0x11): k='*';break;case (0x21): k=0;break;case (0x41): k='#';break;case (0x81): k='D';break;}return(k);}/******************************按键检测并返回按键值*************************************/ uchar keynum(void){uchar row,col,i;DDRD=0x0F;PORTD=0xF0;//KeyRead=PIND; //读取键盘结果//KeyRead&=0x0f; //屏蔽高四位//if((P1&0xf0)!=0xf0)if((PIND&0xf0)!=0xf0){Delay5Ms();Delay5Ms();if((PIND&0xf0)!=0xf0){row=PIND^0xf0; //确定行线i=0;PORTD=a[i];////精确定位while(i<4){if((PIND&0xf0)!=0xf0){col=~(PIND&0xff); //确定列线break; //已定位后提前退出}else{i++;PORTD=a[i];}}}else{return 0;}while((PORTD&0xf0)!=0xf0);return (row|col); //行线与列线组合后返回}else return 0; //无键按下时返回0}/********************************一声提示音,表示有效输入*************************************/ void OneAlam(void){PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//}/*********************************二声提示音,表示操作成功*********************************/void TwoAlam(void){PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//Delay5Ms();PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//}/*******************************三声提示音,表示错误************************************/ void ThreeAlam(void){PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//Delay5Ms();PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//Delay5Ms();PORTA&=~BIT(6);//Delay5Ms();PORTA|=BIT(6);//}/*****************显示输入的N个数字,用H代替以便隐藏*************************************/ void DisplayOne(void){// DisplayOneChar(9+N,1,'*');write_1602com(yi+5+N);write_1602dat('*');}/***********************************显示提示输入**************************************/ void DisplayChar(void){unsigned char i;if(pass==1){//DisplayListChar(0,1,LockOpen);write_1602com(er);for(i=0;i<16;i++){write_1602dat(LockOpen[i]);}}else{if(N==0){//DisplayListChar(0,1,Error);write_1602com(er);for(i=0;i<16;i++){write_1602dat(Error[i]);}}else{//DisplayListChar(0,1,start_line);write_1602com(er);for(i=0;i<16;i++){write_1602dat(start_line[i]);}}}}/**************************************************************************************/ void DisplayInput(void){uchar i;if(CorrectCont==1){//DisplayListChar(0,0,Input);write_1602com(er);for(i=0;i<16;i++){write_1602dat(Input[i]);}}}/******************************************重置密码*******************************/ void ResetPassword(void){uchar i;uchar j;if(pass==0){pass=0;DisplayChar();ThreeAlam();}else{if(ReInputEn==1){if(N==6){ReInputCont++;if(ReInputCont==2){for(i=0;i<6;){if(TempPassword[i]==InputData[i]) //将两次输入的新密码作对比i++;else{//DisplayListChar(0,1,Error);write_1602com(er);for(j=0;j<16;j++){write_1602dat(Error[j]);}ThreeAlam(); //错误提示pass=0;ReInputEn=0; //关闭重置功能,ReInputCont=0;DisplayChar();break;}}if(i==6){//DisplayListChar(0,1,ResetOK);write_1602com(er);for(j=0;j<16;j++){write_1602dat(ResetOK[j]);}TwoAlam(); //操作成功提示WrToROM(TempPassword,0,6); //将新密码写入24C02存储///////// ReInputEn=0;}ReInputCont=0;CorrectCont=0;}else{OneAlam();//DisplayListChar(0, 1, again); //显示再次输入一次write_1602com(er);for(j=0;j<16;j++){write_1602dat(again[j]);}for(i=0;i<6;i++){TempPassword[i]=InputData[i]; //将第一次输入的数据暂存起来}}N=0; //输入数据位数计数器清零}}}}/****************************输入密码错误超过三过,报警并锁死键盘********************************/ void Alam_KeyUnable(void){PORTD=0x00;//{PORTA^=BIT(6);//Delay5Ms();}}/*************************************取消所有操作***********************/void Cancel(void){uchar i;uchar j;//DisplayListChar(0, 1, start_line);write_1602com(er);for(j=0;j<16;j++){write_1602dat(start_line[j]);}TwoAlam(); //提示音for(i=0;i<6;i++){InputData[i]=0;}PORTB|=BIT(7);//关闭锁PORTA|=BIT(6);//报警关operation=0; //操作标志位清零pass=0; //密码正确标志清零ReInputEn=0; //重置输入充许标志清零ErrorCont=0; //密码错误输入次数清零CorrectCont=0; //密码正确输入次数清零ReInputCont=0; //重置密码输入次数清零PORTB|=BIT(5);s3_keydown=0;key_disable=0;N=0; //输入位数计数器清零}/*******************************确认键,并通过相应标志位执行相应功能************************/ void Ensure(void){uchar i,j;RdFromROM(CurrentPassword,0,6); //从24C02里读出存储密码if(N==6){if(ReInputEn==0) //重置密码功能未开启{for(i=0;i<6;){if(CurrentPassword[i]==InputData[i]){i++;}else{ErrorCont++;if(ErrorCont==3) //错误输入计数达三次时,报警并锁定键盘{write_1602com(er);for(i=0;i<16;i++){write_1602dat(Error[i]);}doAlam_KeyUnable();while(1);}else{TIMSK|=BIT(2); //开启定时key_disable=1; //锁定键盘pass=0;break;}}}if(i==6){CorrectCont++;if(CorrectCont==1) //正确输入计数,当只有一次正确输入时,开锁,{//DisplayListChar(0,1,LockOpen);write_1602com(er);for(j=0;j<16;j++){write_1602dat(LockOpen[j]);}TwoAlam(); //操作成功提示音PORTB&=~BIT(7);//开锁///////////////////////////////////pass=1; //置正确标志位TIMSK|=BIT(2); //开启定时/////////////////////////PORTB&=~BIT(5);//开锁指示灯亮//////////////////////////////for(j=0;j<6;j++) //将输入清除{InputData[i]=0;}}else//当两次正确输入时,开启重置密码功能{//DisplayListChar(0,1,SetNew);write_1602com(er);for(j=0;j<16;j++){write_1602dat(SetNew[j]);}TwoAlam(); //操作成功提示ReInputEn=1; //允许重置密码输入CorrectCont=0; //正确计数器清零}}else//============当第一次使用或忘记密码时可以用131420对其密码初始化{if((InputData[0]==1)&&(InputData[1]==3)&&(InputData[2]==1)&&(InputData[3]==4)&&(InputData[4]==2)&& (InputData[5]==0)){WrToROM(initpassword,0,6); //强制将初始密码写入24C02存储//DisplayListChar(0,1,initword); //显示初始化密码write_1602com(er);for(j=0;j<16;j++){write_1602dat(initword[j]);}TwoAlam();Delay400Ms();TwoAlam();N=0;}else{//DisplayListChar(0,1,Error);write_1602com(er);for(j=0;j<16;j++){write_1602dat(Error[j]);}ThreeAlam(); //错误提示音pass=0;}}}else//当已经开启重置密码功能时,而按下开锁键,{//DisplayListChar(0,1,Er_try);write_1602com(er);for(j=0;j<16;j++){write_1602dat(Er_try[j]);}ThreeAlam();}}else{//DisplayListChar(0,1,Error);write_1602com(er);for(j=0;j<16;j++){write_1602dat(Error[j]);}ThreeAlam(); //错误提示音pass=0;}N=0; //将输入数据计数器清零,为下一次输入作准备operation=1;}/********************************************************************************************/ void main(void){uchar KEY,NUM;uchar i,j;segg();port_init();Delay400Ms(); //启动等待,等LCM讲入工作状态lcd_init(); //LCD初始化write_1602com(yi);//日历显示固定符号从第一行第0个位置之后开始显示PORTD=0xFF;TCCR1B=0X05;//1024分频//5msTCNT1H=0XFF;//TCNT1L=0XC5;//TIMSK|=BIT(2);SREG|=BIT(7);for(i=0;i<16;i++){write_1602dat(name[i]);//向液晶屏写日历显示的固定符号部分}write_1602com(er);//时间显示固定符号写入位置,从第2个位置后开始显示for(i=0;i<16;i++){write_1602dat(start_line[i]);//写显示时间固定符号,两个冒号}write_1602com(er+9); //设置光标位置write_1602com(0x0f); //设置光标为闪烁Delay5Ms(); //延时片刻(可不要)N=0; //初始化数据输入位数while(1){if(key_disable==1)Alam_KeyUnable();elsePORTA|=BIT(6); //关报警KEY=keynum();if(KEY!=0){if(key_disable==1){second=0;}else{NUM=coding(KEY);{switch(NUM){case ('A'): ; break;case ('B'): ; break;case ('C'): ; break;case ('D'): ResetPassword(); break; //重新设置密码case ('*'): Cancel(); break; //取消当前输入case ('#'): Ensure(); break; //确认键,default:{//DisplayListChar(0,1,Input);write_1602com(er);for(i=0;i<16;i++){write_1602dat(Input[i]);}operation=0;if(N<6) //当输入的密码少于6位时,接受输入并保存,大于6位时则无效。
单片机电子密码锁课程设计
基于单片机的电子密码锁设计一、设计要求和条件1.1 设计要求根据单片机开发板所提供的元件特性和硬件电路,编写相关的程序,通过实验开发板实现电子密码锁在LCD1602上显示的功能。
1.搭建proteus仿真电路图平台,模拟单片机要实现的功能;2.焊接单片机系统开发板;3.编写程序,实现密码锁相关功能;4.下载并调试程序,实现密码锁的具体功能。
1.2 设计目的1.熟练掌握KEIL软件的使用方法;2.熟练掌握PROTEUS软件的使用方法;3.掌握单片机I/O接口的工作原理;4.掌握中断系统的工作原理;5.掌握液晶LCD1602的工作原理及编程方法;6.掌握蜂鸣器的编程使用;7.掌握行列式键盘的工作原理及编程使用方法;8.掌握单片机的ISP下载使用方法。
1.3 功能概述本设计是基于单片机的密码锁设计方案,根据要求,给出了该单片机密码锁的硬件电路和软件程序,同时给出了硬件设计方案、软件流程图、C 语言源程序及详细注释等内容,由于单片机实验板上的矩阵键盘为3*3的,则规定0-5号键为数字键,6-8号键为功能键,其中该密码锁的具体功能介绍如下:(1)按“8”号键则输入密码,初始密码为012345,在LCD1602上显示密码值为“******”(密码是保密的),输完6位后键盘就锁定,在LCD1602上显示密码是否正确,若输入的密码长度小于6位,则1602等待密码输入。
(2)若密码输入正确后,则绿色的发光二极管亮表示开锁,并且1602上显示“you are right!”,等待是否修改密码。
(3)密码输入错误时显示“code is wrong”,接着会给你第二、第三次机会输入密码,如果三次密码都错误时,发出“叮咚”的报警声,且红色报警指示灯不停闪烁,按复位键清除报警。
(4)按“7”号键表示若密码不小心输入时,可以删除输入错误的密码。
(5)按“6”修改密码,要求输入原密码是正确的,然后按该键后,蓝色密码修改指示灯会亮,并且1602上会显示“Input new code”,输入正确要求再次输入,两次输入一致提示“Modify right!!!”并返回主菜单。
单片机电子密码锁课程设计.doc
一、
1.1设计要求
根据单片机开发板所提供的元件特性和硬件电路,编写相关的程序,通过实验开发板实现电子密码锁在LCD1602上显示的功能。
1.搭建proteus仿真电路图平台,模拟单片机要实现的功能;
2.焊接单片机系统开发板;
3.编写程序,实现密码锁相关功能;
4.下载并调试程序,实现密码锁的具体功能。
(2)若密码输入正确后,则绿色的发光二极管亮表示开锁,并且1602上显示“you are right!”,等待是否修改密码。
(3)密码输入错误时显示“code is wrong”,接着会给你第二、第三次机会输入密码,如果三次密码都错误时,发出“叮咚”的报警声,且红色报警指示灯不停闪烁,按复位键清除报警。
1.3
本设计是基于单片机的密码锁设计方案,根据要求,给出了该单片机密码锁的硬件电路和软件程序,同时给出了硬件设计方案、软件流程图、C语言源程序及详细注释等内容,由于单片机实验板上的矩阵键盘为3*3的,则规定0-5号键为数字键,6-8号键为功能键,其中该密码锁的具体功能介绍如下:
(1)按“8”号键则输入密码,初始密码为012345,在LCD1602上显示密码值为“******”(密码是保密的),输完6位后键盘就锁定,在LCD1602上显示密码是否正确,若输入的密码长度小于6位,则1602等待密码输入。
[3]宋彩利.单片机原理与C51编程[M].西安交通大学出版社,2007
附录
附录II实物显示
#include <reg52.h>
#define ulong unsigned long
#define uint unsigned int
#define uchar unsigned char
第八章 基于AT24C02的电子密码锁的设计
图 8-7 应答信号时序
六、I2C 总线的传送格式
I2C 总线的传送格式为主从式, 对系统中的某一器件来说有四种工作方式: 主发送方式、 从发送方式、主接收方式、从接收方式。 单片机发送 24C02 接收为主发送方式。 主器件产生开始信号以后, 发送的第一个字节为控制字节。 前七位为从器件的地址片选 信号。最低位为数据传送方向位(高电平表示读从器件,低电平表示写从器件) ,然后发送 一个选择从器件片内地址的字节,来决定开始读写数据的起始地址。接着再发送数据字节, 可以是单字节数据,也可以是一组数据,由主器件来决定。从器件每接收到一个字节以后, 都要返回一个应答信号(ASK=0) 。主器件在应答时钟周期高电平期间释放 SDA 线,转由从器 件控制,从器件在这个时钟周期的高电平期间必须拉低 SDA 线,并使之为稳定的低电平,作 为有效的应答信号。
第八章 基于 AT24C02 的电子密码锁的设计
8.1 硬件电路的设计
图 8-1 AT24C02 硬件电路
备注:SCL、SDA 引脚需要接 10K 的上拉电阻,学习板上,所有引脚都也接 10K 上拉电阻。
8.2 I C 总线的 AT24C02 存储器简介
一、什么是 I2C 总线
I C 总线(Inter Integrated Circuit Bus) :是 Philips 公司推出的串行总线标准(为 二线制) 。总线上扩展的外围器件及外设接口通过总线寻址,是具备总线仲裁和高低速设备 同步等功能的高性能多主机总线。 串行数据线 SDA 和串行时钟线 SCL 构成的,可发送和接收数据。 2 2 所有挂接在 I C 总线上的器件和接口电路都应具有 I C 总线接口,且所有的 SDA/SCL 同名端 相连。总线上所有器件要依靠 SDA 发送的地址信号寻址,不需要片选线。 特点:组成系统结构简单,占用空间小,芯片管脚的数量少,无需片选信号,价格低。 允许若干兼容器件共享总线, 应用比较广泛。 总线的长度可达 7.6m, 传送速度可达 400kbps, 2 标准速率为 100kbps。支持多个组件。支持多主控器件(某时刻只能有一个主控器件) 。I C 总线上所有设备的 SDA, SCL 引脚必须外接上拉电阻。
电子密码锁单片机设计完整程序电路
以 STC89C516 单片机为主控制单元,键盘为主要输入单元,结合开锁装置、 报警器和显示器完成整个系统设计。
系统的运行过程大致如下: 假设初始状态为闭锁,此时整个系统只等待按键输入,显示屏 显示“Input password Press key A”。按下 A 后,每按下一个数据键 (即每输入一个密码),lcd1602 显示一个“*”,当密码全部输入完成后, 需按下确认键“#”,此时系统判断密码是否正确,正确则开锁,错误则 报警。若按下密码重置键“*”,则需先输入原密码,正确后请输入新密 码,还要确认一遍新密码。按下删除键可以删除输错的密码。
单片机课程设计
1 系统的总体设计和主要元器件介绍 (1)设计要求
以 STC89C516 单片机为核心器件,结合按键电路、LCD1602 显 示电路、报警指示电路和开锁机构,利用单片机灵活的编程设计和丰富 的 I/O 端口,及其控制的准确性通过软件程序来控制整个系统实现电子 密码锁的以下基本功能:
(2)LCD1602 显示器
接口信号说明:
1602 型 LCD 的接口信号说明如表 2-2 所示。
表 2-2 LCD1602 接口信号说明
2
对全部高中资料试卷电气设备,在安装过程中以及安装结束后进行高中资料试卷调整试验;通电检查所有设备高中资料电试力卷保相护互装作置用调与试相技互术关,系电,力根通保据过护生管高产线中工敷资艺设料高技试中术卷资0配不料置仅试技可卷术以要是解求指决,机吊对组顶电在层气进配设行置备继不进电规行保范空护高载高中与中资带资料负料试荷试卷下卷问高总题中体2资2配,料置而试时且卷,可调需保控要障试在各验最类;大管对限路设度习备内题进来到行确位调保。整机在使组管其高路在中敷正资设常料过工试程况卷中下安,与全要过,加度并强工且看作尽护下可关都能于可地管以缩路正小高常故中工障资作高料;中试对资卷于料连继试接电卷管保破口护坏处进范理行围高整,中核或资对者料定对试值某卷,些弯审异扁核常度与高固校中定对资盒图料位纸试置,卷.编保工写护况复层进杂防行设腐自备跨动与接处装地理置线,高弯尤中曲其资半要料径避试标免卷高错调等误试,高方要中案求资,技料编术试写5交、卷重底电保要。气护设管设装备线备置4高敷、调动中设电试作资技气高,料术课中并3试中、件资且卷包管中料拒试含路调试绝验线敷试卷动方槽设技作案、技术,以管术来及架避系等免统多不启项必动方要方式高案,中;为资对解料整决试套高卷启中突动语然过文停程电机中气。高课因中件此资中,料管电试壁力卷薄高电、中气接资设口料备不试进严卷行等保调问护试题装工,置作合调并理试且利技进用术行管,过线要关敷求运设电行技力高术保中。护资线装料缆置试敷做卷设到技原准术则确指:灵导在活。分。对线对于盒于调处差试,动过当保程不护中同装高电置中压高资回中料路资试交料卷叉试技时卷术,调问应试题采技,用术作金是为属指调隔发试板电人进机员行一,隔变需开压要处器在理组事;在前同发掌一生握线内图槽部纸内故资,障料强时、电,设回需备路要制须进造同行厂时外家切部出断电具习源高题高中电中资源资料,料试线试卷缆卷试敷切验设除报完从告毕而与,采相要用关进高技行中术检资资查料料和试,检卷并测主且处要了理保解。护现装场置设。备高中资料试卷布置情况与有关高中资料试卷电气系统接线等情况,然后根据规范与规程规定,制定设备调试高中资料试卷方案。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include #include #include #include #include #include
#define uchar unsigned char #define uint unsigned int
//上次按键和当前按键序号,该矩阵中序号范围0~15,16表示无按键 uchar pre_keyno=16,keyno=16; uchar code Title_Text[]="your password...";//标题字符串 uchar DSY_BUFFER[16]=" ";//显示缓冲 uchar userpassword[7]=" ";//用户输入的密码 uchar IIC_Password[7]; uchar IS_Valid_User = 0; uchar i = 0; void Beep(); uchar Clear_Password();
sbit LED_OPEN = P2^0;//开锁灯亮 sbit BEEP = P3^7;//蜂鸣器
//=================================================== //延时................ void delay(uint x) { uchar i; while (x--) for(i=0;i<120;i++); } //蜂鸣器子程序 void beep() { uchar i; for(i=0;i<100;i++) { BEEP=~ BEEP; } BEEP=0; } // 清除密码 void clear_password() { uchar i; for(i=0; i<6; i++) { userpassword[i] =' '; DSY_BUFFER[i] =' '; } } // 主程序初始化 void init_main() { P0 = 0xFF; P1 = 0xFF; P2 = 0xFF;
TMOD = 0x02; //T0设置为8位自动重装模式 TH0 = 175; TL0 = 175; TR0 = 1; //启动T0
delay(10); lcd_init(); IIC_24C04_Init(); //初始化24C04 } // 键盘执行功能 void key_main() {
P1 = 0xF0; if(P1 != 0xF0) keyno = keys_scan(); //扫描键盘获取键序号KeyNo if(pre_keyno != keyno) { if(i<=6) { switch ( keyno ) { case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9:
//if ( i<= 6 ) //密码限制在6位以内 // { //如果i为0则执行一次清屏 if (i == 0) display_string(" ",0x40); userpassword[i] = keyno + '0'; userpassword[i+1] = ' ';
//DSY_BUFFER[i] = userpassword[i]; DSY_BUFFER[i] = '*'; DSY_BUFFER[i+1] = ' ';
display_string(DSY_BUFFER,0x40); i++; // } break;
case 10: //按A键开锁 if (strcmp(userpassword,IIC_Password) == 0) { LED_OPEN = 0; //点亮LED Clear_Password(); display_string("Unlock OK! ",0x40); IS_Valid_User = 1; } else { LED_OPEN =1; //关闭LED Clear_Password(); display_string("ERROR ! ",0x40); IS_Valid_User = 0; } i = 0;
break;
case 11: //按B键上锁 LED_OPEN =1; Clear_Password(); display_string(Title_Text,0x00); display_string(" ",0x40); i = 0;
IS_Valid_User = 0; break;
case 12: //按C键设置新密码 //如果是合法用户则提示输入新密码 if ( !IS_Valid_User ) display_string("No rights !",0x40); else { i = 0;
display_string("New Password: ",0x00); display_string(" ",0x40); }
break;
case 13: //按D键保存新密码 if ( !IS_Valid_User ) display_string("No rights !",0x40); else { sendstring(0xa0, 0 , userpassword, 6);
//重新读入刚写的密码 recstring(0xa0, 0 , IIC_Password, 6); IIC_Password[6] = ' ';
i = 0;
display_string(Title_Text,0x00); display_string("Password Saved! ",0x40); }
break;
case 14: //按E键消除所有输入 i = 0;
Clear_Password(); display_string(" ",0x40); } } beep(); pre_keyno = keyno;
} // delay(100); // Beep(); delay(100); P1= 0xF0; while (P1 != 0xF0); //如果有键未释放则等待 while (P1 == 0xF0); //如果没有再次按下按键则等待 } //===================================================================== // 主程序 //----------------------------------------------------------------- //原始程序中相邻两位密码不能相同. //本压缩包中的HEX由修改后的新程序编译生成,允许输入任意密码. //----------------------------------------------------------------- //实训100例中本例内的main函数可用以下代码替换. //改动的主要是main函数中while循环内的代码. //----------------------------------------------------------------- // 主程序 //----------------------------------------------------------------- void main() {
init_main(); display_string(Title_Text,0x00); //在第1行显示标题
//24C04的内容已由初始化BIN文件导入 //将24C04中预先写入的密码读入pass recstring(0xa0, 0 , IIC_Password, 6); IIC_Password[6] = '\0';
while(1) { key_main(); // P1= 0xF0; // while (P1 != 0xF0); //如果有键未释放则等待 // while (P1 == 0xF0); //如果没有再次按下按键则等待 } }
#ifndef __LCD1602_H__ #define __LCD1602_H__
#include #define uint unsigned int #define uchar unsigned char
sbit rs = P2^1; sbit rw = P2^2; sbit eq = P2^3;
void delay_lcd(uchar n)