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,一经查实,立即删除!

相关文章

旋转的正方体

<!DOCTYPE html><html lang"zh-cmn-Hans"><head><meta charset"utf-8" /><title>backface-visibility_CSS参考手册_web前端开发参考手册系列</title><meta name"author" content"Joy Du(飘零雾雨),…

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

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

python3 实现对比conf 文件差异

用法&#xff1a; ./conf.py nginx1.conf nginx2.conf > diff.htmlconf.py#!/usr/bin/python import difflib import sys #### Usage: compare_nginx.conf.py filename1 filename2 >diff.html try:textfile1 sys.argv[1]textfile2 sys.argv[2] except Exception as…

mysql----innodb统计信息

对innodb 统计信息的控制可以通过如下几个常用的variables 来实现 1、innodb_stats_persistent&#xff1a; 这个参数控制着innodb的统计信息是否持久化到磁盘&#xff0c;先说明一下持久化到磁盘是什么意思&#xff1b;通常来说统计信息只保存在内存中&#xff0c;也就是说如果…

linux pid t 头文件_linux系统调用相关头文件

Linux C 一些函数 所属的头文件 2011-03-07 10:25:07分类&#xff1a; LINUX在编写程序时&#xff0c;有时总是不记得所使用的函数在哪个库函数中。现在先把自己以前经常用到的函数头文件总结一下。 有不对的地方还请指教。1&#xff0c;系统调用 文件的操作函数#inlclude &…

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;员工及管理者…

iOS网络编程实践--NSStream实现TCP Socket iPhone客户端

客户端我们使用iPhone应用程序&#xff0c;画面比较简单。点击发送按钮&#xff0c;给服务器发送一些字符串过去。点击接收按钮就会从服务器读取一些字符串&#xff0c;并且显示在画面上。 有关客户端应用的UI部分不再介绍了&#xff0c;我们直接看代码部分&#xff0c;Socket客…

Mocha 和 Chai 入门初探

转载自楼主个人博客 Mocha 和 Chai 入门初探Chai 在和 jest 作比较的时候, 两者主要的不同就是 jest 的集成度比较高内置断言库, 而 mocha 需要搭配额外的断言库, 在此选择了比较流行的 chai 作为断言库. 风格的选择 其中 chai 又有好几种断言风格, 我们经常见到的其实就是 BDD…

ios把数据传递到另一个页面_IOS 应用之间的跳转和数据传递详解

说明&#xff1a;本文介绍app如何打开另一个app,并且传递数据。一、简单说明新建两个应用&#xff0c;分别为应用A和应用B.实现要求:在appA的页面中点击对应的按钮&#xff0c;能够打开appB这个应用。1.新建两个应用&#xff0c;分别为A和B.142354418874108[1].png150002248248…

Libevent初探

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

ServerSocketChannel API用法

java.nio.channels 类 ServerSocketChannel java.lang.Objectjava.nio.channels.spi.AbstractInterruptibleChanneljava.nio.channels.SelectableChanneljava.nio.channels.spi.AbstractSelectableChanneljava.nio.channels.ServerSocketChannel所有已实现的接口&#xff1a; C…

jq分页 不刷新页面_jQuery无刷新分页完整实例代码

本文实例讲述了jQuery无刷新分页实现方法。分享给大家供大家参考&#xff0c;具体如下&#xff1a;这款jQuery分页示例&#xff0c;是分页经典形式&#xff0c;兼容性也做的好&#xff0c;网页上的分页代码&#xff0c;分享给大家。运行效果截图如下&#xff1a;在线演示地址如…

为什么要写年终总结

2016只剩下不到百分之一的时间了&#xff0c;网上陆续看到各种企业或个人的总结或盘点&#xff0c;公司也必须规定每个员工要做年度工作总结&#xff0c;或许是环境释然&#xff0c;心里也有无数次要做总结的念头&#xff0c;尤其是月末年末这种感觉更重&#xff0c;但却没静下…

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

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

tiny4412u-boot烧写及根文件系统制作(不进入终端问题)

http://m.blog.csdn.net/article/details?id51400196&#xff08;转&#xff09; VMware12 环境&#xff1a;ubuntu12.4 开发板&#xff1a;tiny4412 首先烧写bootloader&#xff0c;我用一个8G的内存卡&#xff0c;现在不说sd卡的制作过程了&#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…