【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 = 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 = 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);     //基本指令, 扩充指令为34H
106     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中写入一个字节的数据info
void 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;         //RST
sbit 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 P3
uchar 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
  • 软件仿真

时间: 2024-10-29 17:58:43

【51项目】电子密码锁设计的相关文章

51单片机电子密码锁设计

51单片机电子密码锁设计

毕业设计:数字密码锁设计.pdf

32个单片机类毕业设计集锦,给广大大四学生的福利,即将要毕业了,是不是要交毕业设计呢,关于电子设计,单片机,proteus等硬软件的毕业设计在闯客网技术论坛都有大量的实例,都是免费下载的,毕业设计根本不用愁,还免费下载呢,这么好的事只有闯客网做得出来,这个群可以免费获取:613377058 下载地址:https://bbs.usoftchina.com/thread-208784-1-1.html 目录: 1.16×16点阵(滚动显示)论文+程序 2.电气工程系06届毕业设计开题报告 1.2M3

项目设计之一-------------项目包的设计原则(原)

很久之前把几大名著<敏捷软件开发>.<设计模式>.<大话设计模式>.<重构-改善既有代码的设计>.<轻量级J2EE企业应用实战-Struts+Spring+Hibernate整合开发>等研究了一遍,然后就想做个项目来综合以上知识,现在把项目设计的思路写出来. 包的设计 最好遵循包设计六大原则.前三增加内聚:1.重用发布等价原则:2.共同重用原则.3共同封闭原则.后三增加解耦:4.无环依赖原则,5.稳定依赖原则,6.未定抽象原则.具体参看<敏

实验七 团队作业3—团队项目的原型设计与开发

实验七 团队作业3-团队项目的原型设计与开发 实验时间 2018-5-3(5/4) Deadline: 2018-5-9 10:00,以团队随笔博文提交至班级博客的时间为准. 评分标准: l  按时交 – 根据实验七评分细则打分(满分15分,团队博文与原型设计成果) l  本实验为团队任务,团队成员成绩以团队博文成绩为准 l  晚交 - 0分 l  抄袭 - 倒扣本次作业分数 l  如对作业分数有意见,可有一次向评分助教申诉机会 关于软件原型方法 原型方法就是快速地建立可运行的.概略的系统,之后

天津地铁出行线路规划项目需求分析与设计思路分析

天津地铁出行线路规划项目需求分析与设计思路分析 项目概要 以下是天津地铁线路总图,本项目的受众可以通过本软件,获得天津市地铁出行最便捷,最快速的线路推荐. 需求分析 实现一个帮助进行地铁出行路线规划的命令行程序. 支持地铁线路的更改,站点更改.取消与添加,以及线路的局部封闭. 支持查询线路的所有站点. 支持查询到某终止站点的途径最少站点的路线. 数据存储结构分析 由于单一的线路表与站点表是无法表示如此复杂的地铁线路情况的. 有多个前驱的站点如:,以及有多个后继的站点如:,这种情况无法只通过这两个

手势识别项目小组——数据库设计心得

因为我们的项目是算法类,所以项目本身的需求不太明确.设计数据库的过程其实本身也是在进一步明确需求的过程. 这是我们画出的用例图: 以下是我们小组成员的数据库设计心得: JJ: 通过本次数据库设计的过程,我经历了很多也学会了很多. 首先因为课程组的要求是设计出至少15张表,而我们想要达到15张表是很困难的.我们的设计想法是先根据我们之前设计的原型先设计出一些表,根据登陆.注册.历史记录等设计了几张表.但是这些表也基本是基于用户而设计的,后来我们也寻求了指导老师的帮助,指导老师帮忙想了一个损失函数表

OA项目4:BaseDao设计

首注:本学习教程为传智播客汤阳光讲师所公布的免费OA项目视频的文字版,本人用此来加强巩固自己开发知识,如有网友转载,请注明.谢谢. 一 为什么要设计BaseDao? 为了减少代码量,用最少的代码实现最多的功能. 二 建立一个cn.clear.oa.base包,在包下写一个接口类,有最基本的增删改查功能,具体内容如下: 1 package cn.clear.oa.base; 2 3 import java.util.List; 4 5 public interface BaseDao<T> {

ssm+RESTful bbs项目后端主要设计

小谈: 帖主妥妥的一名"中"白了哈哈哈.软工的大三狗了,也即将找工作,怀着丝丝忐忑接受社会的安排.这是第一次写博客(/汗颜),其实之前在学习探索过程中,走了不少弯路,爬过不少坑.真的挺感谢一路上的前辈们的博客也好,随笔也好,哪怕是评论,或多或少解决了一些问题.我感觉学技术的过程中,记录下自己解决问题的过程.经验,如果可以的话能分享,其实也挺好.希望能从“中白”变“大白”,再到佬行列哈哈. 简介: 这次主要是基于ssm框架和mysql在idea上写的,restful风格使用起来url感觉

《结对编项目作业名称-设计文档》

项目:关灯游戏,所用软件,pygame 成员:祁昊,刘孝东 关灯游戏设计文档: pygame作为一种游戏编程语言,以其简单性.可移植性等优点,得到了广泛地应用,特别是py使用比c,c++等语言简便,使其成为网络编程首选编程语言.,Pygame是跨平台Python模块,专为电子游戏设计.基于这样一个设想,所有需要的游戏功能和理念都(主要是图像方面)都完全简化为游戏逻辑本身,所有的资源结构都可以由高级语言提供,如Python.工具tile编辑器和一个关卡编辑器.得到广大程序员的接受和认可. "关灯游