基于51单片机的密码锁Proteus仿真

news2024/12/23 12:44:31

文章目录

  • 一、密码锁
    • 1.题目要求
    • 2.思路
    • 3.仿真图
      • 3.1 未仿真时
      • 3.2 初始界面
      • 3.3 输入密码界面
      • 3.4 开锁成功界面
      • 3.5 修改密码界面
      • 3.6 输入密码错误界面
    • 4.仿真程序
      • 4.1 矩阵按键
      • 4.2 液晶显示1602
      • 4.3 存储模块2402
  • 二、总结


一、密码锁

1.题目要求

以51单片机为核心,设计并制作密码锁

基本功能如下:

  1. 设置6位初始密码,密码输入正确时,液晶显示屏上会显示密码正确;
  2. 当输入密码错误时能够删除和清零,如果密码输入错误次数达到3次,将会进行蜂鸣器报警;
  3. 密码能够掉电保存,可通过功能按键"“修改密码”键来重新设置密码。
  4. 要求用户输入密码时,不可直接显示输入的值,要求用显示“*”代替。

2.思路

首先先画个51单片机:

这里的P0为什么需要画上拉排阻呢?

主要原因是因为P0口是开漏输出的,即集电极开路输出(OC门)。这种输出结构没有内置的上拉电阻,因此不能直接输出高电平。当P0口需要输出高电平时,必须通过外部电路提供驱动电流,这时就需要加上拉电阻来实现。上拉电阻的作用是将电平拉高,通常连接到电源正极(VCC),以便在需要时提供电流给负载,从而确保P0口能够正确地输出高电平信号。

在这里插入图片描述

要使用到多个按键进行设置密码,又不想浪费IO资源,第一时间想到的是用矩阵按键,不懂的小伙伴可以看看之前的介绍基于51单片机的矩阵按键扫描的proteus仿真(附源码)

在这里插入图片描述

显示的话,液晶显示屏想到的是LCD1602,但是在Proteus仿真里面叫做LM016L,不懂的小伙伴可以看看之前的介绍基于51单片机的LCD1602显示的proteus仿真(附源码)

在这里插入图片描述
要求断电能够保存密码,那就是要用到EEPROM芯片,这里用个简单的24C02来进行存储,,不懂的小伙伴可以看看之前的介绍基于51单片机的AT24C02存储的proteus仿真(附源码)

报警的话,用个蜂鸣器进行报警即可。
在这里插入图片描述
既然是密码锁,那肯定能模拟开锁,这里选用继电器来驱动电机转动达到一个模拟的效果。

在这里插入图片描述

3.仿真图

3.1 未仿真时

在这里插入图片描述

3.2 初始界面

在这里插入图片描述

3.3 输入密码界面

在这里插入图片描述

3.4 开锁成功界面

在这里插入图片描述

3.5 修改密码界面

在这里插入图片描述

3.6 输入密码错误界面

在这里插入图片描述

4.仿真程序

4.1 矩阵按键

/*******************************************************************************
* 函 数 名         : Key_Check()
* 函数功能		   : 检测有矩阵按键按下并读取键值
* 输    入         : 无
* 输    出         : KeyValue:按键值,无按键按下返回20
*******************************************************************************/
uchar Key_Check(void)
{
	static bit flag_key=0;
	uchar KeyValue=20; //无按键按下返回20
	uchar a=0;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f)  	 //读取按键是否按下
	{
		if(!flag_key){				//判断之前的按键状态
			flag_key=1;				//按键状态1,按下状态
			Delay_Us(1000);		 //延时10ms进行消抖
			if(GPIO_KEY!=0x0f)	 //再次检测键盘是否按下
			{		
				GPIO_KEY=0x0f;	//测试列
				switch(GPIO_KEY)
				{
					case(0X07):	KeyValue=0;break;
					case(0X0b):	KeyValue=1;break;
					case(0X0d): KeyValue=2;break;
					case(0X0e):	KeyValue=3;break;
				}			
				GPIO_KEY=0xf0;	//测试行
				switch(GPIO_KEY)
				{
					case(0X70):	KeyValue=KeyValue;break;
					case(0Xb0):	KeyValue=KeyValue+4;break;
					case(0Xd0): KeyValue=KeyValue+8;break;
					case(0Xe0):	KeyValue=KeyValue+12;break;
				}		
			}
		}
	}else flag_key=0;
	return KeyValue;	//返回按键值
}

4.2 液晶显示1602

/*******************************************************************************
* 函 数 名         : Read_Busy()
* 函数功能		     : 忙检测函数,判断bit7是0,允许执行;1禁止
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Read_Busy()           
{
    unsigned char sta;     
    LCD1602_DB = 0xff;
    LCD1602_RS = 0;
    LCD1602_RW = 1;
    do
    {
        LCD1602_EN = 1;
        sta = LCD1602_DB;
        LCD1602_EN = 0;    //使能,用完就拉低,释放总线
    }while(sta & 0x80);
}

/*******************************************************************************
* 函 数 名         : Lcd1602_Write_Cmd()
* 函数功能		     : LCD写命令
* 输    入         : cmd:命令
* 输    出         : 无
*******************************************************************************/
void Lcd1602_Write_Cmd(unsigned char cmd)     
{
    Read_Busy();
    LCD1602_RS = 0;
    LCD1602_RW = 0;
    LCD1602_DB = cmd;
    LCD1602_EN = 1;
    LCD1602_EN = 0;    
}

/*******************************************************************************
* 函 数 名         : Lcd1602_Write_Data()
* 函数功能		     : LCD写数据
* 输    入         : dat: 数据
* 输    出         : 无
*******************************************************************************/
void Lcd1602_Write_Data(unsigned char dat)   
{
      Read_Busy();
      LCD1602_RS = 1;
      LCD1602_RW = 0;
      LCD1602_DB = dat;
      LCD1602_EN = 1;
      LCD1602_EN = 0;
}

/*******************************************************************************
* 函 数 名         : LcdSetCursor()
* 函数功能		     : 设置坐标
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void LcdSetCursor(unsigned char x,unsigned char y)  
{
    unsigned char addr;
    if(y == 0)
        addr = 0x00 + x;
    else
        addr = 0x40 + x;
    
    Lcd1602_Write_Cmd(addr|0x80);
}

/*******************************************************************************
* 函 数 名         : DisplayOneChar()
* 函数功能		     : 按指定位置显示一个字符
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData)
{
	Y &= 0x1;
	X &= 0xF; //限制X不能大于15,Y不能大于1
	if (Y) X |= 0x40; //当要显示第二行时地址码+0x40;
	X |= 0x80; //算出指令码
	Lcd1602_Write_Cmd(X); //发命令字
	Lcd1602_Write_Data(DData); //发数据
}

/*******************************************************************************
* 函 数 名         : LcdShowStr()
* 函数功能		     : 显示字符串
* 输    入         : x,y:当前字符的坐标;*str:字符串
* 输    出         : 无
*******************************************************************************/
void LcdShowStr(unsigned char x,unsigned char y,unsigned char *str)     
{
    LcdSetCursor(x,y);      //当前字符的坐标
    while(*str != '\0')
    {
        Lcd1602_Write_Data(*str++);
    }
}

/*******************************************************************************
* 函 数 名         : Lcd1602_Init()
* 函数功能		     : LCD1602初始化
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/
void Lcd1602_Init()              //
{
    Lcd1602_Write_Cmd(0x38);    //打开,5*8,8位数据
    Lcd1602_Write_Cmd(0x0c);
    Lcd1602_Write_Cmd(0x06);
    Lcd1602_Write_Cmd(0x01);    //清屏   
}

4.3 存储模块2402

//IIC启动
void Start(void)
{
	SDA1=1;
	Delay_Us(2);
	SCL1=1;
	Delay_Us(2);//建立时间是SDA保持时间>4.7us
	SDA1=0;
	Delay_Us(2);//保持时间是>4us
	SCL1=0;			
	Delay_Us(2);
}

//IIC停止
void Stop(void)
{
	SDA1=0;
	Delay_Us(2);
	SCL1=1;
	Delay_Us(2);//建立时间大于4.7us
	SDA1=1;
	Delay_Us(4);		
}

//IIC发送字节
//dat:要发送的字节
void Send_Byte(unsigned char dat)
{
	unsigned char a=0,b=0;
	for(a=0;a<8;a++)//要发送8位,从最高位开始
	{
		SDA1=dat>>7;	 //起始信号之后SCL=0,所以可以直接改变SDA信号
		dat=dat<<1;
		Delay_Us(2);
		SCL1=1;
		Delay_Us(2);//建立时间>4.7us
		SCL1=0;
		Delay_Us(2);//时间大于4us
	}	
}

//IIC检查应答
bit Check_Ack(void)
{
	//unsigned char t;
	SCL1=0;
	SDA1=1;
	Delay_Us(2);
	SCL1=1;
	Delay_Us(2);
	CY=SDA1;
	SCL1=0;
	Delay_Us(2);	
	return(CY);
}

//IIC应答
void Ack(void)
{ 
	SDA1=0;   //EEPROM通过在收到每个地址或数据之后
	SCL1=1;   //置SDA低电平的方式确认表示收到读SDA口状态
	Delay_Us(1);
 	SCL1=0;
	Delay_Us(1);
	SDA1=1;
}

//IIC无应答
void NoAck(void)
{
	SDA1=1;
	SCL1=1;
	Delay_Us(1);
	SCL1=0;
}

//IIC接收字节
unsigned char Receive_Byte(void)
{
	unsigned char a=0,dat=0;
	SDA1=1;			//起始和发送一个字节之后SCL都是0
	Delay_Us(2);
	for(a=0;a<8;a++)//接收8个字节
	{
		SCL1=1;
		Delay_Us(2);
		dat<<=1;
		dat|=SDA1;
		Delay_Us(2);
		SCL1=0;
		Delay_Us(2);
	}
	return dat;		
}

//At24cxx读写数据
//addr:要读/写数据的地址
//*dat:要读/写的数据
//length;数据的长度
//RW:1:写,0:读
void At24c02_RW(unsigned char addr,unsigned char *dat,unsigned char length,bit RW)
{
	Start();
	Send_Byte(0xa0);//发送写器件地址
	Check_Ack();
	Send_Byte((unsigned char)addr);//发送要写入内存地址
	Check_Ack();
	if(RW)		 //写
	{	while(length--)
		{
			Send_Byte(*dat++);
			Check_Ack();	
		}
	}
	else
	{
		Start();
		Send_Byte(0xa1);
		Check_Ack();
		while(--length)
		{
			*dat++=Receive_Byte();
			 Ack();
		}
		*dat=Receive_Byte();//读取最后一个字节
		NoAck();
	}
	Stop();
	if(RW)
	Delay_Us(1000);
}

二、总结

今天主要讲了基于51单片机的密码锁Proteus仿真

感谢你的观看!

在这里插入图片描述

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

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

相关文章

【原创实现 设计模式】Spring+策略+模版+工厂模式去掉if-else,实现开闭原则,优雅扩展

1 定义与优点 1.1 定义 策略模式&#xff08;Strategy Pattern&#xff09;属于对象的⾏为模式。他主要是用于针对同一个抽象行为&#xff0c;在程序运行时根据客户端不同的参数或者上下文&#xff0c;动态的选择不同的具体实现方式&#xff0c;即类的行为可以在运行时更改。…

C++:静态断言内存对齐

静态断言 C中的断言assert (1)直接参考&#xff1a;https://www.cnblogs.com/lvchaoshun/p/7816288.html (2)C的assert是运行时检测发现错误&#xff0c;而不是编译时 (3)C在编译时错误用#error来输出C静态断言 (1)C引入static_assert(表达式, “提示字符串”)来实现编译时的静…

[数据集][目标检测]婴儿状态睡觉哭泣检测数据集VOC+YOLO格式7109张3类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;7109 标注数量(xml文件个数)&#xff1a;7109 标注数量(txt文件个数)&#xff1a;7109 标注…

【MySQL基础篇】SQL指令:DQL及DCL

1、DQL DQL - 介绍 DQL英文全称是Data Query Language(数据查询语言)&#xff0c;数据查询语言&#xff0c;用来查询数据表中的记录。&#xff08;在MySQL中应用是最为广泛的&#xff09; 查询关键字&#xff1a;SELECT DQL - 语法 SELECT 字段列表 FROM 表名列表 WHER…

代码随想录算法训练营第四十七天| 188.买卖股票的最佳时机IV ,309.最佳买卖股票时机含冷冻期 ,714.买卖股票的最佳时机含手续费

188. 买卖股票的最佳时机 IV - 力扣&#xff08;LeetCode&#xff09; class Solution {public int maxProfit(int k, int[] prices) {int[][] dp new int[prices.length][2*k];for(int i0;i<2*k;i){if(i%2 0){dp[0][i] -prices[0];}else{dp[0][i] 0;} }for(int i1;i…

LeetCode题练习与总结:环形链表Ⅱ--142

一、题目描述 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测…

C语言 | Leetcode C语言题解之第206题反转链表

题目&#xff1a; 题解&#xff1a; struct ListNode* reverseList(struct ListNode* head) {if (head NULL || head->next NULL) {return head;}struct ListNode* newHead reverseList(head->next);head->next->next head;head->next NULL;return newHea…

Camera Raw:增强

Camera Raw 中的增强 Enhance命令基于 AI 技术提升图像的质量&#xff0c;可用于降噪、生成清晰的细节以及提高图像的分辨率。 ◆ ◆ ◆ 主要用途 1、高 ISO 图像降噪 勾选“去杂色” Denoise&#xff0c;可轻松消除使用高 ISO 设置或在低光环境下拍摄的照片中的噪点。 可以对…

Nettyの粘包、半包问题框架解决方案自定义协议

1、Netty框架是如何解决粘包、半包问题 关于粘包&#xff0c;半包问题&#xff0c;在前面几篇中都有提及&#xff0c;我们简单的复习一下。 粘包指的是客户端发出的多条消息&#xff0c;被服务端当做一条进行接收。半包指的是客户端发出一条完整的消息&#xff0c;在传输的过程…

鸿蒙项目实战-月木学途:1.编写首页,包括搜索栏、轮播图、宫格

效果展示 搜索栏制作 相关知识回顾 输入框组件TextInput 单行输入框类型.type(InputType.Normal)//基本输入框.type(InputType.Password)//密码.type(InputType.Email)//邮箱.type(InputType.Number)//数字.type(InputType.PhoneNumber)//电话号.type(InputType.Normal).type…

boston房价预测--机器学习Boston数据分析

1.采用散点图绘制相关性。 #分析波士顿房价数据集的数据相关性 import numpy as np import pandas as pd import matplotlib.pyplot as plt #载入数据集 data_url "http://lib.stat.cmu.edu/datasets/boston" raw_df pd.read_csv(data_url, sep"\s", …

Java数据结构6-栈与队列

1. 栈(Stack) 1.1 概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶&#xff0c;另一端称为栈底。栈中的数据元素遵守后进先出LIFO&#xff08;Last In First Out&#xff09;的原则 压栈…

第11章 规划过程组(11.5创建WBS)

第11章 规划过程组&#xff08;一&#xff09;11.5创建WBS&#xff0c;在第三版教材第380~383页&#xff1b; 文字图片音频方式 视频22 第一个知识点&#xff1a;主要输入 1、项目管理计划 范围管理计划 定义了如何根据项目范围说明书创建WBS2、项目文件 项目范围说明…

Uboot重定位

Uboot重定位 一、重定位的意义二、介绍一些重定位相关的表项结构(节)三、uboot的重定位过程:一、重定位的意义 uboot的重定位有两次,第一次是在编译成镜像后,在makefile中调用进行处理的,其调用tools/riscv_prelink.c的代码进行重定位处理(主要就是对重定位表中的R_RIS…

为什么IP地址会被列入黑名单?

您是否曾经历过网站访客数量骤减或电子邮件投递失败的困扰&#xff1f;这背后或许隐藏着一个常被忽略的原因&#xff1a;您的IP地址可能已经被列入了黑名单内。尽管您并没有进行任何违法的网络操作&#xff0c;但这个问题依然可能出现。那么&#xff0c;究竟黑名单是什么&#…

巴黎成为欧洲AI中心 大学开始输出AI创始人

来自Dealroom 的数据显示&#xff0c;在欧洲和以色列AI创业公司中&#xff0c;法国的AI创业公司资金最充裕。Mistral、Owkin、Hugging Face等法国企业已经融资23亿美元&#xff0c;比英国、德国AI创业公司都要多。 一名大学生走出校门凭借聪明才智和一个黄金点子成为富豪&#…

36.基于多目标螳螂优化算法的微电网优化matlab

微♥关注“电击小子程高兴的MATLAB小屋”获取资源 基于螳螂优化算法的多目标优化算法 求解微电网多目标优化调度 比较不同目标函数寻优对调度结果的影响 第1种.将两个目标函数值归一化相加&#xff0c;取相加后最小的目标值的粒子&#xff0c;即寻找折衷解并画图 第2种寻找…

Matlab|【需求响应】空调负荷需求响应模型

1主要内容 程序主要复现《溫控负荷的需求响应潜力评估及其协同优化管理研究_谢敦见》2.5部分章节的内容&#xff0c;建立空调负荷的聚合模型&#xff0c;考虑调节空调温度对空调响应潜力的影响&#xff0c;程序结果充分说明随着上调温度增大&#xff0c;响应程度逐渐增大。 具…

CVE-2019-12272 Openwrt可视页面LuCi命令注入漏洞复现(更新中)

漏洞简介 参考内容&#xff1a; CVE-2019-12272 OpenWrt图形化管理界面LuCI命令注入分析 | Math & Sec &#xff0c;HACHp1的个人博客 CVE-2019-12272 OpenWrt图形化管理界面LuCI命令注入分析_openwrt 图形界面-CSDN博客 exploits/CVE-2019-12272 at master oreosES/exp…

PDF处理篇:如何调整 PDF 图像的大小

将视觉效果无缝集成到 PDF 中的能力使它们成为强大的通信工具。然而&#xff0c;笨拙的图像大小会迅速扰乱文档的流程&#xff0c;阻碍清晰度和专业性。幸运的是&#xff0c;GeekerPDF 和Adobe Acrobat等流行的应用程序提供了用户友好的解决方案来应对这一挑战。这个全面的指南…