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

简介

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

硬件设计

首先我们进行硬件的设计,密码锁的硬件部分还是很简单的,首先我们需要一个51单片机的最小系统,在Proteus中芯片并不需要外接晶振,直接放上芯片就可以使用,我选择AT89C52单片机,并给P0口外接一排上拉电阻来提升驱动能力,c299ec978332e6ac66e3440c97e4cf8b.png
接下来是界面显示部分,之前说过显示部分使用的是LCD1602,LCD的电路如下图,5fdd9b469da314052394f4a77df0c757.png
首先我来简单介绍一下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的键盘就够了,引脚与单片机的连接如下,ec0e32478c8ec5b1500cc6f04f164f90.png
也可以使用按键自己连接一个矩阵键盘有助于对程序的理解。

软件设计

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

    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;        }            }

51ec01d6327eb4fb45075d8711239bed.png
在密码输入函数里我们调用键盘扫描函数,当有按键按下时我们就将对应的键值保存到输入密码的数组里,然后将每一个输入的按键的键值显示在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;        }    }

bf59ffc262a9a7c2ab37b0eb97aa477a.pngaac37c41897d46669b1bd82239f007f7.png
密码锁的密码为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;            }        }    }

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

b2c1f1ea8d67fc0316ecf85361f0bfe6.gif

点“阅读原文”,文章!

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/457353.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

8数据提供什么掩膜产品_博硕能为你提供什么产品?

自动喷漆设备应用于线条、木门、橱柜、楼梯、套房家具、办公家具、木饰面板、外墙保温装饰一体板板等产品领域&#xff0c;针对NC、PU、UV、水性漆和氟碳漆等不同种类的油漆&#xff0c;进行自动化喷涂和干燥作业。自动喷漆设备有多种规格型号&#xff0c;分为不同的喷涂方式。…

jsp页面验证码(完整实例)

项目结构如下&#xff0c;MyEclipse中新建一个Web Project&#xff0c;取名servlet 1、src下new一个servlet类 package com.servlet;import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.IOExcept…

开源oa_圈子哥推荐一款基于 Spring Boot 开发 OA 开源产品,学习/搞外快都是不二选择!...

点击上方蓝字关注「程序员的技术圈子」今天圈子哥给大家推荐一套Spring Boot 开发 OA系统&#xff0c;系统功能齐全&#xff0c;不管是用来学习或者搞外快都是不错的选择&#xff0c;clone下来吧&#xff01;办公自动化(OA)是面向组织的日常运作和管理&#xff0c;员工及管理者…

Libevent初探

Libevent 是一个用C语言编写的、轻量级的开源高性能网络库&#xff0c;主要有以下几个亮点&#xff1a;事件驱动&#xff08; event-driven&#xff09;&#xff0c;高性能;轻量级&#xff0c;专注于网络&#xff0c;不如 ACE 那么臃肿庞大&#xff1b;源代码相当精炼、易读&am…

特别慢_背什么都特别慢,该怎么提高记忆力?

考研是一项全方位的比拼&#xff0c;除了每天进行知识点的复习&#xff0c;还要做题、总结&#xff0c;最后还得进行背诵记忆&#xff0c;其实什么科目都需要背的&#xff0c;就算数学&#xff0c;该记的概念和公式也是要记忆的&#xff0c;因为会做题更快&#xff0c;提高效率…

第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...

3.1 万亿级数据洪峰下的分布式消息引擎 前言 通过简单回顾阿里中间件(Aliware)消息引擎的发展史&#xff0c;本文开篇于双11消息引擎面临的低延迟挑战&#xff0c;通过经典的应用场景阐述可能会面临的问题 - 响应慢&#xff0c;雪崩&#xff0c;用户体验差&#xff0c;继而交易…

Linux目录结构和常用命令

一、Linux目录结构 你想知道为什么某些程序位于/bin下&#xff0c;或者/sbin&#xff0c;或者/usr/bin&#xff0c;或/usr/sbin目录下吗&#xff1f;例如&#xff0c;less命令位于/usr/bin目录下。为什么没在/bin中&#xff0c;或/sbin&#xff0c;或/usr/sbin目录中&#xff1…

挂载nfs文件系统_综合架构-day38-NFS服务补充

1.如何让nfs永久挂载-2种方法开机自启动文件1.vim /etc/rc.d/rc.local需要修改执行权限chmod x /etc/rc.d/rc/localmount -t nfs 172.16.1.31:/upload/ /mnt/2.vim /etc/fstab172.16.1.31:/upload /mnt nfs defaults 0 02.exportfs 加载配置生效&#xff0c;等价于优雅重启[15:…

A Neural Algorithm of Artistic Style

本系列文章由 yhl_leo 出品&#xff0c;转载请注明出处。 文章链接&#xff1a; http://blog.csdn.net/yhl_leo/article/details/53931536 1. 资源 Paper: A Neural Algorithm of Artistic StyleTensorFlow version in GitHub: anishathalye/neural-styleCaffe version in GitH…

CSS布局奇淫技巧之--各种居中

居中是我们使用css来布局时常遇到的情况。使用css来进行居中时&#xff0c;有时一个属性就能搞定&#xff0c;有时则需要一定的技巧才能兼容到所有浏览器&#xff0c;本文就居中的一些常用方法做个简单的介绍。 注&#xff1a;本文所讲方法除了特别说明外&#xff0c;都是兼容I…

手写数字识别中多元分类原理_广告行业中那些趣事系列:从理论到实战BERT知识蒸馏...

导读&#xff1a;本文将介绍在广告行业中自然语言处理和推荐系统实践。本文主要分享从理论到实战知识蒸馏&#xff0c;对知识蒸馏感兴趣的小伙伴可以一起沟通交流。摘要&#xff1a;本篇主要分享从理论到实战知识蒸馏。首先讲了下为什么要学习知识蒸馏。一切源于业务需求&#…

linux zip/unzip命令

2019独角兽企业重金招聘Python工程师标准>>> 语  法&#xff1a;zip [-AcdDfFghjJKlLmoqrSTuvVwXyz$][-b <工 作目录>][-ll][-n <字 尾字符串>][-t <日 期时间>][-<压 缩效率>][压 缩文件][文件...][-i <范本样式>][-x <范本样式…

在Windows下不使用密码远程登陆Linux

在登陆Linux进行管理的时候我们通常会使用用户名和密码进行登陆&#xff0c;这样一来是比较麻烦&#xff0c;二来是不安全&#xff0c;为了解决这个问题&#xff0c;我们可以使用公私钥 (public keys和private keys)进行认证。简单来说公钥存放在服务器上&#xff0c;私钥存放在…

Core Data

简介 Core Data是iOS5之后才出现的一个框架&#xff0c;它提供了对象-关系映射(ORM)的功能&#xff0c;即能够将OC对象转化成数据&#xff0c;保存在SQLite数据库文件中&#xff0c;也能够将保存在数据库中的数据还原成OC对象。在此数据操作期间&#xff0c;我们不需要编写任何…

2017将转行进行到底

2016 年说着转行&#xff0c;最后还是在匆匆中找了一份老本行&#xff0c;此刻的心情还是无爱&#xff0c;毕竟螺丝一直分不清啊&#xff0c;不喜欢就是不喜欢。看了django的教程&#xff0c;不得不感叹国外的书写的相对优秀一点&#xff0c;《learning django web development…

mysql非主键索引_主键索引和非主键索引的区别

1. 什么是最左前缀原则&#xff1f;以下回答全部是基于MySQL的InnoDB引擎例如对于下面这一张表如果我们按照 name 字段来建立索引的话&#xff0c;采用B树的结构&#xff0c;大概的索引结构如下如果我们要进行模糊查找&#xff0c;查找name 以“张"开头的所有人的ID&#…

优美的配色方案设计

2019独角兽企业重金招聘Python工程师标准>>> 怎么做好设计配色一直是个难题&#xff0c;虽然网站上有各种各样的色库&#xff0c;但配色仍然至关重要&#xff0c;不得已的话可以亲自动手&#xff0c;况且乐趣满满。 这个没有一套标准&#xff0c;所以看自己怎么喜欢…

mysql死锁释放时间参数_【Mysql】mysql 事务未提交导致死锁 Lock wait timeout exceeded; try restarting transaction 解决办法...

问题场景问题出现环境&#xff1a;1、在同一事务内先后对同一条数据进行插入和更新操作&#xff1b;2、多台服务器操作同一数据库&#xff1b;3、瞬时出现高并发现象&#xff1b;不断的有一下异常抛出&#xff0c;异常信息&#xff1a;org.springframework.dao.CannotAcquireLo…

springmvc视图解析器_SpringMVC视图及REST风格

什么是视图解析器&#xff1f;springMVC用于处理视图最重要的两个接口是ViewResolver和View。ViewResolver的主要作用是把一个逻辑上的视图名称解析成一个真的的视图&#xff0c;而SpringMVC中用于把View对象呈现给客户端的是View对象本身&#xff0c;而ViewResolver只是把逻辑…

mysql5.7.x 1251_MySql-8.0.x免安装版下载与配置,Navicat打开数据库链接报错1251的解决办法...

概述MySQL从5.7一下子跳到了MySQL8.0, 其中的变化必然是很大的, 这里就不说了, 本文主要讲解最新版MySQL安装的事情.实际上5.7版本后的mysql免安装版都是没有data文件和my.ini文件的&#xff0c;下面再具体说明怎么生成&#xff0c;注意不能自己手动新建.下载下载程序必然去官网…