AT89C51单片机电子密码锁.pdf
AT89C51 单片机电子密码锁#include main.h /*LCD PART START*/5ms 延时 void Delay5Ms(void)unsigned int TempCyc=5552;while(TempCyc-);/读状态 unsigned char ReadStatusLCM(void)LCM_Data=0 xFF;LCM_RS=0;LCM_RW=1;LCM_E=0;LCM_E=0;LCM_E=1;Delay5Ms();while(LCM_Data&Busy);/检测忙信号 return(LCM_Data);/写数据 void WriteDataLCM(unsigned char WDLCM)ReadStatusLCM();/检测忙 LCM_Data=WDLCM;LCM_RS=1;LCM_RW=0;LCM_E=0;/若晶振速度太高能够在这后加小的延时 LCM_E=0;/延时 LCM_E=1;/写指令 void WriteCommandLCM(unsigned char WCLCM,BuysC)/BuysC 为 0 时忽略忙检测 if(BuysC)ReadStatusLCM();/根据需要检测忙 LCM_Data=WCLCM;LCM_RS=0;LCM_RW=0;LCM_E=0;LCM_E=0;LCM_E=1;/读数据 unsigned char ReadDataLCM(void)LCM_RS=1;LCM_RW=1;LCM_E=0;LCM_E=0;LCM_E=1;return(LCM_Data);void LCMInit(void)/LCM 初始化 LCM_Data=0;WriteCommandLCM(0 x38,0);/三次显示模式设置,不检测忙信号 Delay5Ms();WriteCommandLCM(0 x38,0);Delay5Ms();WriteCommandLCM(0 x38,0);Delay5Ms();WriteCommandLCM(0 x38,1);/显示模式设置,开始要求每次检测忙信号 WriteCommandLCM(0 x08,1);/关闭显示 WriteCommandLCM(0 x01,1);/显示清屏 WriteCommandLCM(0 x06,1);/显示光标移动设置 WriteCommandLCM(0 x0C,1);/显示开及光标设置 /按指定位置显示一个字符,x 表示列,Y 表示行 void LCD_write_char(unsigned char X,unsigned char Y,unsigned char DData)Y&=0 x1;X&=0 xF;/限制 X 不能大于 15,Y 不能大于 1 if(Y)X|=0 x40;/当要显示第二行时地址码+0 x40;X|=0 x80;/算出指令码 WriteCommandLCM(X,0);/这里不检测忙信号,发送地址码 WriteDataLCM(DData);/按指定位置显示一串字符 void LCD_write_string(unsigned char X,unsigned char Y,unsigned char code*DData)unsigned char ListLength;ListLength=0;Y&=0 x1;X&=0 xF;/限制 X 不能大于 15,Y 不能大于 1 while(*DData)/若到达字串尾则退出 0就是 0 if(X=0 xF)/X坐标应小于 0 xF LCD_write_char(X,Y,*DData);/显示单个字符 DData+;X+;/*/#include#include#define uchar unsigned char#define uint unsigned int /*LCD PART START*/void delay(uint z)/延时 uint x,y;for(x=z;x0;x-)for(y=124;y0;y-);sbit e=P25;sbit rw=P26;sbit sr=P27;uchar code name=zxs;uchar code name1=zcf;uchar code name2=zx;void write_com(uchar com)int rs;rs=0;P0=com;delay(5);e=1;delay(5);e=0;void write_data(uchar date)int rs;rs=1;P0=date;delay(5);e=1;delay(5);e=0;void init()e=0;rw=0;write_com(0 x38);write_com(0 x0c);write_com(0 x06);write_com(0 x01);write_com(0 x80);void display()uchar i;for(i=0;i3;i+)write_data(namei);write_com(0 x80+0 x40);for(i=0;i3;i+)write_data(name1i);void main()init();display();#include#define uchar unsigned char uchar starbuf10;uchar wordbuf8;uchar pw8=1,2,3,4,5,6,7,8;uchar pwbuf8;uchar count=0;/初始没有输入密码,计数器设为 0 uchar inputflag=0;/先处于密码输入状态,非密码修改状态 bit enterflag=0;/没有按下确认键 bit pwflag=0;/密码标志先置为 0 sbit warn=P36;#define lcd_data P0 sbit rs=P27;sbit rw=P26;sbit e=P25;/LCD1602 驱动程序/void delay_1602(unsigned int i)while(i-);void enrw()rs=0;rw=0;e=0;delay_1602(250);e=1;write_data(uchar c)lcd_data=c;rs=1;rw=0;e=0;delay_1602(250);e=1;init_lcd(void)/初始化 lcd_data=0 x01;/清屏幕 enrw();lcd_data=0 x38;/数据长度为 8 位,双行显示,5*7 字符。enrw();lcd_data=0 x0c;/打开显示开关 enrw();lcd_data=0 x06;/地址计数递增,显示屏不移动 enrw();write_cmd(uchar m)/写命令,注意与写数据的区别 lcd_data=m;enrw();display(uchar row,uchar colum,uchar*s)/行 列 字符 写字符串,简单的指针应用 uchar p;if(row=1)p=0 x82+colum-1;else p=0 xC0+colum-1;write_cmd(p);for(;*s!=0;s+)write_data(*s);void lcd_display(unsigned char a,unsigned char b,unsigned char i)/行 列 数 switch(i)case 0:display(a,b,0);break;/*0*/case 1:display(a,b,1);break;/*1*/case 2:display(a,b,2);break;/*2*/case 3:display(a,b,3);break;/*3*/case 4:display(a,b,4);break;/*4*/case 5:display(a,b,5);break;/*5*/case 6:display(a,b,6);break;/*6*/case 7:display(a,b,7);break;/*7*/case 8:display(a,b,8);break;/*8*/case 9:display(a,b,9);break;/*9*/default:break;/*键消抖延时函数*/void delay(unsigned int i)int j;for(;i0;i-)for(j=0;j100;j+);/*键扫描函数*/uchar keyscan(void)uchar scancode,tmpcode;P1=0 xf0;/发全 0 行扫描码 if(P1&0 xf0)!=0 xf0)/若有键按下 delay(2);/延时去抖动 if(P1&0 xf0)!=0 xf0)/延时后再推断一次,去除抖动影响 scancode=0 xfe;/第一行变低 while(scancode&0 x10)!=0)/逐行扫描 P1=scancode;/输出行扫描码 if(P1&0 xf0)!=0 xf0)/本行有键按下 tmpcode=(P1&0 xf0)|0 x0f;/*返回特征字节码,为 1 的位即对应于行与列*/return(scancode)+(tmpcode);else scancode=(scancode1)|0 x01;/行扫描码左移一位 return(0);/无键按下,返回值为 0 /*密码比较函数*/bit pwcmp(void)bit flag;uchar i;for(i=0;i8;i+)if(pwi=pwbufi)flag=1;else flag=0;i=8;return(flag);/*密码清除函数*/void pwclk(unsigned char k)unsigned char i;for(i=0;i8;i+)wordbufi=0;/数码管显示 00000000 starbufi=0;if(k=0)pwbufi=0;/用 FFFFFF 清除已经输入的密码 else pwi=0;/用 FFFFFF 清除已经输入的密码 /*按键声响函数*/void alarm()unsigned char i;for(i=0;i200;i+)warn=!warn;delay(1);/*密码报警函数*/void alarm1()unsigned int i;for(i=0;i0)for(a=0;a150;a+)warn=!warn;delay(1);for(b=0;b150;b+)warn=!warn;delay(2);i-;/*按键处理函数*/void key_conduct(unsigned char a,unsigned char b)switch(a)case 0 x11:/1 行 1 列,数字 0 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=0;else pwcount=0;wordbufcount=0;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x21:/1 行 2 列,数字 1 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=1;else pwcount=1;wordbufcount=1;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x41:/1 行 3 列,数字 2 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=2;else pwcount=2;wordbufcount=2;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x81:/1 行 4 列,数字 3 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=3;else pwcount=3;wordbufcount=3;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x12:/2 行 1 列,数字 4 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=4;else pwcount=4;wordbufcount=4;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x22:/2 行 2 列,数字 5 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=5;else pwcount=5;wordbufcount=5;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x42:/2 行 3 列,数字 6 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=6;else pwcount=6;wordbufcount=6;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x82:/2 行 4 列,数字 7 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=7;else pwcount=7;wordbufcount=7;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x14:/3 行 1 列,数字 8 if(count8)if(b=0)starbufcount=*;/对应密码位上显示*pwbufcount=8;else pwcount=8;wordbufcount=8;lcd_display(2,count+1,wordbufcount);count+;alarm();break;case 0 x24:/3 行 2 列,数字 9 if(count=3)/假如密码输入错误三次 init_lcd();init_lcd();display(1,0,No access!);alarm2();while(1);while(inputflag=1)/更换密码模式 display(1,0,New password:);key=keyscan();/调用键盘扫描函数 key_conduct(key,inputflag);if(enterflag=1)/假如按下确认键 enterflag=0;/标志位置回 0 count=0;/密码位计数器清零 if(pwflag=1)/假如密码修改正确 inputflag=0;init_lcd();display(1,0,Change finish!);delay(2000);else init_lcd();display(1,0,Change fail!);pwclk(1);alarm1();电路图