草庐IT

基于51单片机LCD1602的简易矩阵键盘密码锁

Y.A.N_c 2023-05-27 原文

写在前面

初次开始写博客,表达方面也许会有很多不足,希望自己能通过这种方式巩固自己的学习和锻炼表达能力,同时也是对于自己学习的记录。

一、功能介绍

  1. 四位密码锁,密码可更改,输入仅四次以内有效
  2. 矩阵键盘定义为1-16,顺序为从左上到右下,1-10号为密码输入键位,对键码取余,输入10时为0, 定义11号键码为确认键,12号键码为取消/结束键
  3. 输入密码可通过取消键随时清零,同时显示清空,输入结束按下确认键后,密码正确则显示"Right","Welcome back!", 停滞一秒后进入下一显示界面;密码错误显示"Error","Input again."
  4. 密码正确后的下一显示界面可以自由发挥

二、程序设计 

1、延时函数

1.1、实现功能

输入参数为延时时间长度,单位为毫秒,用于短暂延时

1.2、设计原理

从STC-ISP 中生成的延时1ms的代码修改得到的延时任意时间的函数

1.3、代码实现

/**
  * @brief 延时函数
  * @param  延迟的时间xms
  * @retval 无
  */

void Delay(unsigned int xms)		//@12.000MHz
{
	unsigned char i, j;
  while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
	
}

2、矩阵键盘函数

2.1、实现功能

将矩阵键盘从左上到右下编为1-16,当按下其中一个按键,松开的一瞬间程序返回该按键对应的键码,如果按下不放,程序将停在此函数;没有按下的时候函数返回值为0.

2.2、设计原理

通过STC89C52开发板原理图我们可以看出,矩阵键盘由八个I/O口驱动,由于51单片机的按键都是按下检测为低电平,松开检测为高电平,所以检测按键按下的方式为:

  1. 先将P17 - P10都置1
  2. 置零第一列, 即P13 = 0,扫描P17 - P14, 若P17 = 0,则S1按下,P16 = 0,则S5按下,以此类推,检测第一列是否有按键按下
  3. 继续以同样的方式检测后三列,即可判断哪个按键按下,返回相应的键码即可

2.3、代码实现

函数说明和定义变量

/**
  * @brief 矩阵键盘读取按键键码
  * @param  无
  * @retval KeyNumber
  如果按键按下不放,程序会停留在此函数,松手一瞬间返回按键键码,没有按键按下时返回0
  */

unsigned char MatrixKey()
{
	unsigned char KeyNumber = 0;

扫描第一列的代码如下

	P1 = 0xFF;
	P1_3 = 0;
	if(P1_7 == 0){Delay(20);while(!P1_7);Delay(20);KeyNumber = 1;}
	if(P1_6 == 0){Delay(20);while(!P1_6);Delay(20);KeyNumber = 5;}
	if(P1_5 == 0){Delay(20);while(!P1_5);Delay(20);KeyNumber = 9;}
	if(P1_4 == 0){Delay(20);while(!P1_4);Delay(20);KeyNumber = 13;}
	

 完整代码就是在函数体里用上面这种格式写四次扫描,简单但冗长就不贴在这里了

3、LCD1602功能函数

LCD1602功能函数有初始化、显示字符、显示无符号/有符号数字、显示字符串等等

函数声明模块

#ifndef __LCD1602_H__
#define __LCD1602_H__

//用户调用函数:
void LCD_Init();
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char);
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String);
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length);
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length);

#endif

本次用到的LCD1602显示函数有LCD_Init、LCD_ShowString、LCD_ShowNum

代码实现段

/**
  * @brief  LCD1602初始化函数
  * @param  无
  * @retval 无
  */
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}
/**
  * @brief  在LCD1602指定位置开始显示所给字符串
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  String 要显示的字符串
  * @retval 无
  */
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}
/**
  * @brief  在LCD1602指定位置开始显示所给数字
  * @param  Line 起始行位置,范围:1~2
  * @param  Column 起始列位置,范围:1~16
  * @param  Number 要显示的数字,范围:0~65535
  * @param  Length 要显示数字的长度,范围:1~5
  * @retval 无
  */
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

4、主函数设计

4.1、实现功能

接收按键按下函数返回的键码,对其进行判断,未松开不执行后面的程序,松开后判断四次以内按下密码是否正确,11 号键为确认键,12号为取消/结束键

4.2、设计原理

定义Count用于计数,keyNum用于接收按键返回键码

unsigned int PassWord,Count,KEYPASS = 120;
unsigned char keyNum;

 LCD1602初始化显示初始界面

LCD_Init(); // LCD初始化
Delay(100);
LCD_ShowString(1,1,"PassWord:");

while(1)结构使得程序不停止一直执行

返回按键键码在10以内,且输入在四次以内,对每一次按下的键码进行左移位操作形成四位密码

    			if(keyNum <= 10) //定义1-10号为密码输入键
				{
					if(Count<4)   //只允许输入四次有效
					{
						PassWord = 10*PassWord;  //密码位数左移一位
						PassWord += keyNum%10;   //获取一位密码
					}
					Count++;                     //计数输入次数

接下来就是关于密码正确与否的相关设计比较简单下面附完整代码

4.3、代码实现

#include <REGX52.H>
#include"LCD1602.h"
#include"Delay.h"
#include"MatrixKey.h"

unsigned int PassWord,Count,KEYPASS = 120;
unsigned char keyNum;

void main()
{
	
	LCD_Init(); // LCD初始化
	Delay(100);
	LCD_ShowString(1,1,"PassWord:");
	while(1)
	{
		keyNum = MatrixKey();  //接收返回的按键键码
		if(keyNum)             //判断是否有非取消键按下,没有按键按下执行显示键码;按键按下未松开不执行;
		{
			if(keyNum != 12)    //定义12号键为取消&退出键
			{
				if(keyNum <= 10) //定义1-10号为密码输入键
				{
					if(Count<4)   //只允许输入四次有效
					{
						PassWord = 10*PassWord;  //密码位数左移一位
						PassWord += keyNum%10;   //获取一位密码
					}
					Count++;                     //计数输入次数
				}
				LCD_ShowNum(2,1,PassWord,4);     //显示当前输入的密码
				
				if(keyNum == 11)      //定义11号键为确认键
				{
					Delay(200);
					if(PassWord == KEYPASS)    //密码正确
					{
						LCD_ShowString(1,11,"Right");
						Delay(200);
						LCD_ShowString(2,1,"Welcome back!");
						Delay(1000);
						LCD_Init();
						LCD_ShowString(1,1,"11.27    Sunday");
						LCD_ShowString(2,1,"I love you.");
					}
					else                       //密码错误
					{
						LCD_ShowString(1,11,"Error");
						PassWord = 0;
						Count = 0;
						Delay(500);
						LCD_ShowString(2,1,"Input again");
						Delay(1000);
						LCD_Init();           	 //初始化LCD
						LCD_ShowString(1,1,"PassWord:");
					}
				}
			}				
			else                //按下取消键
			{
				Count = 0;
				PassWord = 0;
				LCD_Init();      //初始化LCD
				LCD_ShowString(1,1,"PassWord:");
			}	
		}	
	}
}

三、结果展示

初始界面

 密码错误

 密码正确

 

1秒后跳转

 用来给对象表白了hhh

有关基于51单片机LCD1602的简易矩阵键盘密码锁的更多相关文章

  1. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  2. 基于C#实现简易绘图工具【100010177】 - 2

    C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.

  3. C51单片机——实现用独立按键控制LED亮灭(调用函数篇) - 2

    说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时

  4. kvm虚拟机安装centos7基于ubuntu20.04系统 - 2

    需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc

  5. ruby-on-rails - (Ruby,Rails) 基于角色的身份验证和用户管理...? - 2

    我正在寻找用于Rails的优质管理插件。似乎大多数现有的插件/gem(例如“restful_authentication”、“acts_as_authenticated”)都围绕着self注册等展开。但是,我正在寻找一种功能齐全的基于管理/管理角色的解决方案——但不是简单地附加到另一个非基于角色的解决方案。如果我找不到,我想我会自己动手......只是不想重新发明轮子。 最佳答案 RyanBates最近做了两个关于授权的railscast(注意身份验证和授权之间的区别;身份验证检查用户是否如她所说的那样,授权检查用户是否有权访问资源

  6. ruby - 在 Rakefile 中动态生成 Rake 测试任务(基于现有的测试文件) - 2

    我正在根据Rakefile中的现有测试文件动态生成测试任务。假设您有各种以模式命名的单元测试文件test_.rb.所以我正在做的是创建一个以“测试”命名空间内的文件名命名的任务。使用下面的代码,我可以用raketest:调用所有测试require'rake/testtask'task:default=>'test:all'namespace:testdodesc"Runalltests"Rake::TestTask.new(:all)do|t|t.test_files=FileList['test_*.rb']endFileList['test_*.rb'].eachdo|task|n

  7. ruby - 如何使用 Ruby 基于字母数字字符串生成颜色? - 2

    我想要像“嘿那里”这样的东西变成,例如,#316583。我希望将任意长度的字符串“归结”为十六进制颜色。我不知道从哪里开始。我在想,每个字符串的MD5散列都是不同的-但如何将该散列转换为十六进制颜色数字? 最佳答案 你可以只取几位前几位:require'digest/md5'color=Digest::MD5.hexdigest('Mytext')[0..5] 关于ruby-如何使用Ruby基于字母数字字符串生成颜色?,我们在StackOverflow上找到一个类似的问题:

  8. 【自动驾驶环境感知项目】——基于Paddle3D的点云障碍物检测 - 2

    文章目录1.自动驾驶实战:基于Paddle3D的点云障碍物检测1.1环境信息1.2准备点云数据1.3安装Paddle3D1.4模型训练1.5模型评估1.6模型导出1.7模型部署效果附录show_lidar_pred_on_image.py1.自动驾驶实战:基于Paddle3D的点云障碍物检测项目地址——自动驾驶实战:基于Paddle3D的点云障碍物检测课程地址——自动驾驶感知系统揭秘1.1环境信息硬件信息CPU:2核AI加速卡:v100总显存:16GB总内存:16GB总硬盘:100GB环境配置Python:3.7.4框架信息框架版本:PaddlePaddle2.4.0(项目默认框架版本为2.3

  9. ruby - 规范测试基于 EventMachine 的(Reactor)代码 - 2

    我正在尝试整个BDD方法并想测试AMQP基于Vanilla的方面Ruby我正在写的应用程序。选择Minitest后作为与其他名副其实的蔬菜框架不同的平衡功能和表现力的测试框架,我着手编写此规范:#File./test/specs/services/my_service_spec.rb#Requirementsfortestrunningandconfigurationrequire"minitest/autorun"require"./test/specs/spec_helper"#Externalrequires#MinitestSpecsforEventMachinerequire

  10. ruby - JSON的基于流的解析和写入 - 2

    我分1,000个批处理从服务器获取大约20,000个数据集。每个数据集都是一个JSON对象。坚持这会产生大约350MB的未压缩明文。我的内存限制为1GB。因此,我以追加模式将每1,000个JSON对象作为一个数组写入到一个原始JSON文件中。结果是一个包含20个需要聚合的JSON数组的文件。无论如何我都需要触摸它们,因为我想添加元数据。一般RubyYajlParser使这成为可能:raw_file=File.new(path_to_raw_file,'r')json_file=File.new(path_to_json_file,'w')datasets=[]parser=Yajl::

随机推荐