首页 > 代码库 > 【51项目】电子密码锁设计
【51项目】电子密码锁设计
- 设计采用AT89S52单片机作为核心控制单元,配以相应的硬件电路,完成开锁密码的设置、存储、校对、提醒和报警功能。
- 硬件结构
- 整体电路
- 软件结构
- 液晶驱动12864.c
1 /* **************************************************** 2 程序参考地址 3 http://blog.chinaunix.net/uid-21658993-id-1819849.html 4 图片显示 5 http://www.51hei.com/mcu/4161.html 6 ********************************************************/ 7 #ifndef _12864_H_ 8 #define _12864_H_ 9 #define LCD_DATA P0 10 sbit RS = P2^4; //并行的指令/数据选择信号: 1数据, 0命令 11 sbit RW = P2^5; //并行读写选择信号:1读, 0写 12 sbit E = P2^6; //并行使能端:1有效 13 sbit PSB = P2^1; //并/串接口选择:1并,0串 14 sbit RET = P2^3; //复位:0有效 15 16 bit checkBusy() 17 { bit busy; 18 RS = 0; 19 RW = 1; 20 E = 1; 21 delayUs(); 22 busy = (bit)(LCD_DATA&0x80); 23 E = 0; 24 return busy; 25 } 26 void wait() 27 { 28 while(checkBusy()); 29 } 30 void writeCmd(uchar cmd) 31 { 32 wait(); 33 RS = 0; 34 RW = 0; 35 E = 0; 36 delayUs(); 37 LCD_DATA =http://www.mamicode.com/ cmd; 38 delayUs(); 39 E = 1; 40 delayUs(); 41 E = 0; 42 } 43 void writeData(uchar dat) 44 { 45 wait(); 46 RS = 1; 47 RW = 0; 48 E = 0; 49 delayUs(); 50 LCD_DATA =http://www.mamicode.com/ dat; 51 delayUs(); 52 E = 1; 53 delayUs(); 54 E = 0; 55 } 56 57 void setPosition(uchar x, uchar y) //4*8 58 { uchar p; 59 switch(x%4) 60 { 61 case 0: p = 0x80; break; //第0行 62 case 1: p = 0x90; break; //第1行 63 case 2: p = 0x88; break; //第2行 64 case 3: p = 0x98; break; //第3行 65 } 66 p += y; 67 writeCmd(p); 68 } 69 void lcd_mesg(uchar * str) 70 { uchar n = 0; 71 while(str[n] != ‘\0‘) 72 { 73 writeData(str[n++]); 74 } 75 } 76 void lcd_draw(unsigned char code *pic) 77 { 78 unsigned i,j,k; 79 writeCmd(0x34);//扩充指令集 80 for(i=0;i<2;i++)//上半屏和下半屏 81 { 82 for(j=0;j<32;j++)//上下半屏各32行 83 { 84 writeCmd(0x80+j);//写行地址(y地址) 85 if(i==0) 86 { 87 writeCmd(0x80);//写列地址(x地址),上半屏列地址为0x80,下半屏列地址为0x88 88 } 89 else 90 { 91 writeCmd(0x88); 92 } 93 for(k=0;k<16;k++)//写入列数据 94 { 95 writeData(*pic++); 96 } 97 } 98 } 99 writeCmd(0x36);//显示图形100 writeCmd(0x30);//基本指令集101 }102 void init_lcd() 103 {104 PSB = 1; //并口方式105 writeCmd(0x30); //基本指令, 扩充指令为34H106 delayMs(10);107 writeCmd(0x0c); //显示开, 关光标108 delayMs(10);109 writeCmd(0x01); //清屏110 delayMs(10); 111 }112 113 #endif
- 存储驱动24c02.c
#ifndef _24C02_H_#define _24C02_H_uchar flag_lock; //键盘锁定标识,1有效uchar userpsw[6]; uchar adminpsw[6];/*24C02读写驱程序*/sbit scl=P1^1;sbit sda=P1^2;sbit wp=P1^0; //写保护//应答函数:在SCL保持高电平期间,拉低SDA,且保持4us以上,再拉高void iic_ack() { scl=0; //默认初值为0 scl=1; //SCL保持高电平 delay_5us(); sda=1; delay_5us(); sda=0; delay_5us(); scl=0; //SCL结束保持高 sda=1; //SDA返回原值}void iic_start() //开始信号,上升沿{ sda=1; //发送起始条件的数据信号 scl=1; //发送起始条件的时钟信号 delay_5us(); sda=0; //发送起始信号 delay_5us(); scl=0; //钳住IIC总线,准备发送或接收数据 delay_5us(); }void iic_stop() //结束信号,下降沿{ sda=0; //发送结束条件的数据信号 scl=1; //发送结束条件的时钟信号 delay_5us(); sda=1; //发送结束信号 delay_5us();}void writex(unsigned char x) //写一个字节{ unsigned char i; for(i=0;i<8;i++) //循环8次,由高到低赋给SDA { scl=0; //允许更改SDA delay_5us(); //存在边沿时间,需等5us sda=x&0x80; //SDA = 数据和10000000按位与; 串口SDA只送最高位 x=x<<1; delay_5us(); scl=1; delay_5us(); scl=0; }}unsigned char readx() //读一个字节{ unsigned char i,value; for(i=0;i<8;i++) //8次读取1个字节 { scl=0; delay_5us(); scl=1; //保持着SDA的值,以便读出从机数据 delay_5us(); if(sda==1) { value=(value<<1)|1; } if(sda==0) { value=(value<<1)|0; } delay_5us(); } return value;}//向24C02的地址address中写入一个字节的数据infovoid write_24c02(unsigned char address,unsigned char info){ iic_start(); writex(0xae); //24c02芯片地址为111,写方向位0:1010 1110 iic_ack(); writex(address); iic_ack(); writex(info); iic_ack(); iic_stop();}//从24C02的地址address中读取一个字节的数据unsigned char read_24c02(unsigned char address){ unsigned char value; iic_start(); writex(0xae); iic_ack(); writex(address); iic_ack(); iic_start(); writex(0xaf); //24c02芯片地址为111,读方向位1:1010 1111 iic_ack(); value=readx(); iic_stop(); return(value);}void initset_read() { uchar tmp; flag_lock=read_24c02(20); //读出键盘锁定标识并显示,地址20,出厂状态为0 delay_ms(50); for(tmp=0;tmp<6;tmp++) { adminpsw[tmp]=read_24c02(10+tmp); } delay_ms(50); for(tmp=0;tmp<6;tmp++) { userpsw[tmp]=read_24c02(tmp); } delay_ms(50); }void init_24c02() //总线初始化,拉高释放总线,并读出错误计数和密码{ wp=1; scl=1; delay_5us(); sda=1; delay_5us(); initset_read(); //将外部存储器中的密码读入缓存区 }#endif
- 日历/时钟驱动ds1302.c
/* **************************************************** 程序参考地址 http://www.51hei.com/mcu/1730.html********************************************************/#ifndef _DS1302_H_#define _DS1302_H_sbit CLK=P3^6; //DS1302引脚定义sbit IO=P3^4;sbit CE=P3^5; //RSTsbit ACC0=ACC^0;sbit ACC7=ACC^7;extern uchar timer_cnt;void Input_1byte(uchar TD) //DS1302输入一字节数据{ uchar i; ACC=TD; for(i=8;i>0;i--) { IO=ACC0; CLK=1; CLK=0; ACC=ACC>>1; }}uchar Output_1byte(void) //DS1302输出一字节数据{ uchar i; for(i=8;i>0;i--) { ACC=ACC>>1; ACC7=IO; CLK=1; CLK=0; } return(ACC);}void Write_DS1302(uchar add,uchar dat)//向DS1302写{ CE=0; CLK=0; CE=1; Input_1byte(add); Input_1byte(dat); CE=0;}uchar Read_DS1302(uchar add) //从DS1302读{ uchar inf; //信息临时存储变量 CE=0; CLK=0; CE=1; Input_1byte(add); inf=Output_1byte(); CE=0; return(inf);}/**********************DS1302初始化*****************************/void init_1302(){ if(Read_DS1302(0xd1)==0x55) //判断内存单元的内容,是否进行初始化 return; else { Write_DS1302(0x8e,0x00); //关闭写保护 Write_DS1302(0x90,0x00); //电池充电设置 Write_DS1302(0x80,0x00); //秒 Write_DS1302(0x82,0x51); //分 Write_DS1302(0x84,0x17); //时 Write_DS1302(0x86,0x17); //日 Write_DS1302(0x88,0x04); //月 Write_DS1302(0x8c,0x16); //年 Write_DS1302(0xd0,0x55); //写RAM Write_DS1302(0x8e,0x80); //打开写保护 }}/********************************************************** DS1302显示 ***********************************************************/void disp_ds1302(){ uchar min,min1,min2; uchar hour,hour1,hour2; uchar date,date1,date2; uchar mon,mon1,mon2; uchar year,year1,year2;//******读出1302的日期******/ min=Read_DS1302(0x83); //读分:min1=十位,min2=个位 min2=min&0x0f; min1=min>>4; hour=Read_DS1302(0x85); //读时:hour1=十位,hour2=个位 hour2=hour&0x0f; hour1=hour>>4; date=Read_DS1302(0x87); //读日期:date1=十位,date2=个位 date2=date&0x0f; date1=date>>4; mon=Read_DS1302(0x89); //读月份:mon1=十位,mon2=个位 mon2=mon&0x0f; mon1=mon>>4; year=Read_DS1302(0x8d); //读年份:year1=十位,year2=个位 year2=year&0x0f; year1=year>>4; //******显示1302的日期******/ setPosition(0,0); writeData(2+0x30); writeData(0+0x30); writeData(year1+0x30); //年 writeData(year2+0x30); writeData(‘-‘); //- writeData(mon1+0x30); //月 writeData(mon2+0x30); writeData(‘-‘); //- writeData(date1+0x30); //日 writeData(date2+0x30); writeData(‘ ‘); //空格 writeData(hour1+0x30); //时 writeData(hour2+0x30); if(timer_cnt<18) writeData(‘:‘); else writeData(‘ ‘); writeData(min1+0x30); //分 writeData(min2+0x30); }#endif
- 键盘扫描keyscan.c
#ifndef _KEYSCAN_H_#define _KEYSCAN_H_#define keyport P3uchar key=0; //按键值/*------------------------------------------------按键扫描函数,返回扫描键值------------------------------------------------*/unsigned char key_scan(void)//键盘扫描函数,使用行列反转扫描法{ uchar cord_h,cord_l; //行列值中间变量 keyport=0xf0; //行线输出全为0,P3=1111 0000 cord_h=keyport&0xf0; //读入列线值 if(cord_h!=0xf0) //有键按下 { delay_ms(5); //去抖 if(cord_h!=0xf0) { cord_h=keyport&0xf0; //读入列线值 keyport=cord_h|0x0f; //输出当前列线值 delay_ms(5); cord_l=keyport&0x0f; //读入行线值 while((keyport&0x0f)!=0x0f);//等待松开并输出 return(cord_h+cord_l); //键盘最后组合码值 } } return(0xff); //返回"无键按下",键盘不起作用}/*------------------------------------------------键值处理函数,返回扫键值------------------------------------------------*/unsigned char key_value(void) //按下相应的键显示相对应的码值{ switch(key_scan()) { case 0xee:return 0;break; //0 1110 1110 case 0xde:return 1;break; //1 case 0xbe:return 2;break; //2 case 0x7e:return 3;break; //3 case 0xed:return 4;break; //4 case 0xdd:return 5;break; //5 case 0xbd:return 6;break; //6 case 0x7d:return 7;break; //7 case 0xeb:return 8;break; //8 case 0xdb:return 9;break; //9 case 0xbb:return 10;break; //a * 键 case 0x7b:return 11;break; //b # 键 case 0xe7:return 12;break; //c 管理/退出键 case 0xd7:return 13;break; //d 删除键 case 0xb7:return 14;break; //e 清空键 case 0x77:return 15;break; //f 确认键 default:return 0xff;break; }}#endif
- 软件仿真
【51项目】电子密码锁设计
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。