简介

大家好,这篇文章的内容是关于如何用51单片机来制作一个电子密码锁的教程,通过这篇教程可以让刚入门的朋友了解矩阵键盘、LCD1602的使用方法,以及密码输入和修改的程序介绍,我会对每个部分进行详细的介绍。
首先我们来看一下这个密码锁要实现哪些功能:
可通过矩阵键盘进行密码的输入和修改。
可通过LCD1602进行界面的显示。
在了解了我们需要实现的功能后我们就可一开始进行软硬件的设计了。本次密码锁的硬件部分我使用Proteus来进行仿真。

硬件设计

首先我们进行硬件的设计,密码锁的硬件部分还是很简单的,首先我们需要一个51单片机的最小系统,在Proteus中芯片并不需要外接晶振,直接放上芯片就可以使用,我选择AT89C52单片机,并给P0口外接一排上拉电阻来提升驱动能力,
接下来是界面显示部分,之前说过显示部分使用的是LCD1602,LCD的电路如下图,
首先我来简单介绍一下LCD1602的引脚功能:
VSS:接地
VDD:接电源
V0:对比度调整端,使用时可接电位器接地进行对比度调节
RS:寄存器选择,高电平选择数据寄存器,低电平选择指令寄存器
RW:读写信号线,高电平读,低电平写
E:使能端,下降沿写操作,高电平读操作
DB0:数据总线最低位
DB1:数据总线1位
DB2:数据总线2位
DB3:数据总线3位
DB4:数据总线4位
DB5:数据总线5位
DB6:数据总线6位
DB7:数据总线7位
A:背光电源正极
K:背光电源负极
我们可以看到LCD1602一共有上述16个引脚,我来根据图中的接法来介绍一下各个引脚的用法。
VDD和A分别用于给LCD和背光板供电,VSS和K为负极接地,仿真里面我们不需要接A、K引脚。
V0脚就是图中的VEE,这个脚使用来调节LCD的字符对比度,直接接地的时候对比度最高,不过容易出现鬼影,在实际使用的时候我们可以将这个脚通过一个10K的电位器接地来进行对比度的调节,在仿真里我就直接接地了。
RS脚是寄存器选择脚,这个脚我接到单片机的P3.5脚上,我们通过改变这个脚的高低电平可以选择给LCD发送数据还是发送指令。
RW脚是用来设置对LCD的读写操作的,因为在这里我们不需要对LCD进行读取操作,所以我就直接将这个脚接地了,也可以通过IO口来对RW进行设置。
E脚是LCD的使能端,仿真中接的单片机的P3.4脚。
最后的D0~D7脚就是LCD的数据脚,我们将这8个脚接到单片机接了上拉电阻的P0脚,这样就可以给LCD发送指令或数据了。
然后我们需要一个键盘进行密码的输入和修改,在Proteus里我们可以直接搜索KEYPAD来添加矩阵键盘,在这里我们使用一个3*4的键盘就够了,引脚与单片机的连接如下,
也可以使用按键自己连接一个矩阵键盘有助于对程序的理解。

软件设计

在介绍完硬件部分的设计后,我们就可以开始编写程序了,首先讲一下矩阵键盘的程序,

    int keyboard()            //键盘扫描    {        P2 = 0xf7;        k = P2;        k = k & 0xf0;        if(k == 0xf0)        {            kf = 0;        }        if(k != 0xf0)        {            delay(4);            k = P2;            k = k & 0xf0;            if(k != 0xf0)            {                switch(k)                {                    case 0xe0:                        key = 88;mod = 1;kf = 1;                        break;                    case 0xd0:                        key = 0;kf = 1;                        break;                    case 0xb0:                        key = 88;kf = 1;                        break;                    case 0x70:                        key = 88;kf = 1;                        break;                     }            }            }        P2 = 0xfb;        k = P2;        k = k & 0xf0;        if(k != 0xf0)        {            delay(4);            k = P2;            k = k & 0xf0;            if(k != 0xf0)            {                switch(k)                {                    case 0xe0:                        key = 7;kf = 1;                        break;                    case 0xd0:                        key = 8;kf = 1;                        break;                    case 0xb0:                        key = 9;kf = 1;                        break;                    case 0x70:                        key = 88;kf = 1;                        break;                }            }        }        P2 = 0xfd;        k = P2;        k = k & 0xf0;        if(k != 0xf0)        {            delay(4);            k = P2;            k = k & 0xf0;            if(k != 0xf0)            {                switch(k)                {                    case 0xe0:                        key = 4;kf = 1;                        break;                    case 0xd0:                        key = 5;kf = 1;                        break;                    case 0xb0:                        key = 6;kf = 1;                        break;                    case 0x70:                        key = 88;kf = 1;                        break;                }            }        }        P2 = 0xfe;        k = P2;        k = k & 0xf0;        if(k != 0xf0)        {            delay(4);            k = P2;            k = k & 0xf0;            if(k != 0xf0)            {                switch(k)                {                    case 0xe0:                        key = 1;kf = 1;                        break;                    case 0xd0:                        key = 2;kf = 1;                        break;                    case 0xb0:                        key = 3;kf = 1;                        break;                    case 0x70:                        key = 88;kf = 1;                        break;                }            }        }            return key;         }

上面这一段是矩阵键盘的程序,通过改变P1口的值来进行行列检测,同时增加一个标志位kf来判断按键是否松开。有了按键驱动下面就可以编写密码输入的函数了:

    void input()    //密码输入函数    {        keyboard();        if(key!=88)        {            while(kf)            {                keyboard();            }            s = (char)key;            s = s | 0x30;            lcd_pos(d);            write_date(s);            in[i] = key;            i++;            d++;                    key = 88;        }            }


在密码输入函数里我们调用键盘扫描函数,当有按键按下时我们就将对应的键值保存到输入密码的数组里,然后将每一个输入的按键的键值显示在LCD的显示屏上。LCD的驱动程序会在下面讲解。
现在要开始编写LCD的驱动用来显示输入的数字,我们首先需要两个函数,分别给LCD发送数据和指令,程序如下:

    void write_com(uchar com)        //LCD写指令    {        P0=com;        rs=0;        lcden=0;        delay(10);        lcden=1;        delay(10);        lcden=0;    }    void write_date(uchar date)        //LCD写数据    {        P0=date;        rs=1;        lcden=0;        delay(10);        lcden=1;        delay(10);        lcden=0;    }

我们可以通过写数据的函数发送给LCD要显示的数据,可以通过写命令函数向LCD发送指令来对LCD进行相应的设置,相关的指令大家可以自行到网上查阅,以下列出的函数分别用来改变光标位置,LCD初始化设置和清屏。

    void lcd_pos(uchar pos)        //设置LCD显示位置    {                                write_com(pos | 0x80);      }    void init()        //LCD初始化    {        write_com(0x38);        delay(20);        write_com(0x0f);        delay(20);        write_com(0x06);        delay(20);        write_com(0x01);        delay(20);            write_com(0x0c);        delay(20);    }    void clear()        //LCD清屏    {        write_com(0x01);        delay(20);    }

接下来我们可以对输入的密码进行判断,

    void judge()        //密码判断函数    {        if(i==6)        {            for(f = 0;f<6;f++)            {                if(password[f] == in[f])                m++;                }            if(m==6)            {                es = 0;                clear();                lcd_pos(0x03);                write_dates("Welcome!");                delay(1200);                clear();                lcd_pos(0x00);                write_dates("Password:");                lcd_pos(0x45);                write_dates("******");                }            else            {                es++;                clear();                lcd_pos(0x04);                write_dates("Error!");                delay(1200);                if(es == 3)                {                    lcd_pos(0x45);                    write_dates("WARNING");                    delay(5000);                    es = 0;                        clear();                }                lcd_pos(0x00);                write_dates("Password:");                lcd_pos(0x45);                write_dates("******");                                    }            m = 0;            i = 0;            d = 0x45;        }    }


密码锁的密码为6位,当输入6位密码后我们就可以对密码进行判断,判断过程就是将输入密码的数组与保存的密码的数组通过循环进行比较,当输入密码正确后就会显示欢迎界面,等待一段时间再返回密码输入界面,如果密码输入错误则进入错误界面,然后返回密码输入界面,我们可以检测错误的次数如果错误次数太多可以进行类似延长等待时间等操作。
最后就是密码修改的操作。

    void change()        //修改密码函数    {        if(mod==1)        {            lcd_pos(0x00);            write_dates("OldPassword:");            input();            if(i==6)            {                for(f = 0;f<6;f++)                {                    if(password[f] == in[f])                    m++;                    }                if(m==6)                {                    mod=2;                    clear();                    lcd_pos(0x45);                    write_dates("******");                    }                else                {                    clear();                    lcd_pos(0x04);                    write_dates("Error!");                    delay(1200);                    lcd_pos(0x00);                    write_dates("Password:");                    lcd_pos(0x45);                    write_dates("******");                        mod=0;                                    }                m = 0;                i = 0;                d = 0x45;            }            }        if(mod==2)        {            lcd_pos(0x00);            write_dates("NewPassword:");            input();            if(i==6)            {                for(f = 0;f<6;f++)                {                    password[f] = in[f];                }                    lcd_pos(0x44);                write_dates("success!");                delay(1200);                clear();                lcd_pos(0x00);                write_dates("Password:");                lcd_pos(0x45);                write_dates("******");                i = 0;                mod = 0;                d = 0x45;            }        }    }


修改密码需要我们先输入正确密码,然后会进入修改界面,再次输入新密码就可以保存了。过程就是用循环来更新数组内的值,这样一个简单的密码锁就做好了,不过这样的锁有一个缺点,就是设置的密码不会保存,等单片机再次上电后就会恢复到最初始的密码,要想在断电后继续保存密码,我们可以使用EEPROM来进行密码的保存,由于篇幅原因,我会在之后单独介绍EEPROM的读写操作。感谢各位的观看。

点“阅读原文”,文章!

相关产品推荐:树莓派4B 现货,268元起!

51单片机50个实例代码_【附代码】51单片机电子密码锁教程相关推荐

  1. 基于单片机的压力流量报警器(附代码+仿真+论文)

    基于单片机的压力流量报警器(附代码+仿真+论文) **==完整论文+代码+仿真可关注我在主页私我==** 摘要 关键字 第一章绪论 1.1课题背景及其意义 1.2 国内外的研究状况 1.3本文的主要研 ...

  2. html页面文字随机效果,教你用javascript实现随机标签云效果_附代码

    标签云是一套相关的标签以及与此相应的权重.典型的标签云有30至150个标签.权重影响使用的字体大小或其他视觉效果.同时,直方图或饼图表是最常用的代表约12种不同的权数.因此,标签云彩能代表更多的权,尽 ...

  3. python爬虫练习五(补充): 2018年统计用区划代码和城乡划分代码(附代码与全部数据)

    之前爬取过2017年的数据 详见 Python爬虫练习五:爬取 2017年统计用区划代码和城乡划分代码(附代码与全部数据) ,下面有评论说广东省的数据缺少了东莞与中山两个市的数据,检查网页结构发现确实 ...

  4. Dubbo与SpringBoot整合流程(从实例入手,附代码下载)

    场景 Dubbo环境搭建-管理控制台dubbo-admin实现服务监控: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10362 ...

  5. 单片机搭建环境烧录方法_万物互联-stm32单片机简介、烧录、编程及其项目环境搭建...

    万物互联-stm32单片机简介.烧录.编程 前言:stm32单片机这里给出简单介绍,给不了解的朋友普及下硬件端的基本知识,叙述的较为简单,想深入研究的朋友可以去一些官方网站.论坛.博客汲取知识.最下端 ...

  6. 在家用电器中使用单片机应属于微型计算机的,内附答案《单片机原理与应用 》试卷4...

    一.填空题(15分) 1.单片机也可称为或. 2.当单片机复位时PSW=时当前的工作寄存器区是区,R4所对应的存储单元地址为. 3.MCS-51单片机的P0-P4口均是 I/O口,其中的P0口和P2口 ...

  7. 管理员所有权代码_为什么代码所有权糟透了,您永远不应该在有实践的地方工作...

    管理员所有权代码 Code ownership sucks. 代码所有权糟透了. It limits code and stunts your growth as a developer. 它限制了代 ...

  8. 网页漂浮物代码_无代码VS低代码。 有什么不同? 它。 不。 物。

    网页漂浮物代码 You may hear the terms "No Code" and "Low Code" thrown around by develop ...

  9. 51单片机50个实例代码_常用的51单片机代码

    51单片机实验板原理图 1.流水灯实验 #include void delay(unsigned int Cnt){unsigned int t;while(Cnt--){t = 120;while( ...

最新文章

  1. tomcat server.xml中文版
  2. tmux的使用方法和个性化配置
  3. @Async的使用、原理及使用时可能导致的问题
  4. 地图漫游功能的具体体现_骏谷科技|数据中心三维可视化管理系统功能亮点
  5. 动态规划:记忆化搜索
  6. 【收藏】idea 背景图插件
  7. Kotlin协程入门初级篇
  8. HTML基金会2----联系,像, 第,对齐
  9. HCIE RS 全套笔记整理
  10. system verilog语法
  11. python qq群发消息_python qq发消息
  12. 计算机网络初探教案,计算机网络基础知识教案.doc
  13. 什么是单页网站设计?受欢迎的原因在哪?
  14. 系统管理Lesson 14. Performing Database Backups
  15. 诊断和解决row chained and migrated
  16. 小程序笔记(四)发表评论或者普通发帖
  17. windowsmobile 综合 注册表修改 CSDN 推荐tag:mp3 storage gprs 注册表 文件
  18. [Map]-1-Hashtable、HashMap、TreeMap有什么不同
  19. (个人学习)资金托管与资金存管的区别
  20. 微软的技术,直接颠覆了我对听书这件事的看法

热门文章

  1. Hibernate4 注解方法说明
  2. (项目)在线教育平台(六)
  3. 爬虫中的关于字符串的一些理解
  4. 零元学Expression Blend 4 - Chapter 4元件重复运用的观念
  5. java 第11次作业:你能看懂就说明你理解了——this关键字
  6. grunt之Gruntfile(1)
  7. EditPlus 技巧大全:[1]怎么配置PHP编译环境
  8. nyist 17 -----记忆式搜索------Accept
  9. Android 4 学习(19):Services
  10. MongoDB 初学