STM32实战项目—密码锁

news2024/11/13 9:21:06

该项目的完整工程可以在博主的资源里找到,仅供参考。

文章目录

  • 一、任务要求
  • 二、实现方法
    • 2.1 输入密码判断
    • 2.2 管理员模式
    • 2.3 修改密码
  • 三、程序设计
    • 3.1 输入密码判断
    • 3.2 进入管理员模式
    • 3.3 修改密码
  • 四、问题总结
    • 4.1 输入内容一直提示Error
    • 4.2 密码判断一直错误
  • 五、成果展示
    • 5.1 输入密码判断
    • 5.2 进入管理员模式
    • 5.3 修改密码

一、任务要求

设计一款密码锁,通过串口输入输出信息。需要实现以下功能

  • 开机提示“欢迎使用智能密码锁系统”,换行回车后显示“请输入密码”
  • 输入六位任意字符密码,不能是汉字。如果密码正确,返回“密码正确,已开门”。如果密码错误,返回“密码错误,您还有*次输入机会”
  • 如果连续三次输入密码错误,提示“三次密码错误,警报!”。此时,LED闪烁报警
  • 如果输入“Enter(空格)Admin(空格)Mode”,返回“已进入管理员模式”,换行之后显示“请输入管理员密码”。输入密码正确后,提示“管理员密码正确”,进入管理员模式。管理员密码默认为“147258”。如果管理员密码输入错误,提示“管理员密码错误”
  • 进入管理员模式后,提示“请输入新密码”。输入完成一次后提示“请再次输入新密码”。连续两次输入正确后,提示“密码修改成功”,自动退出管理员模式。如果两次密码不一致,会提示“连续两次输入密码不同,请重新输入”。如果新密码与原密码相同,会提示“新密码请勿与原密码相同”
  • 如果输入内容错误,会提示“Error!”,回车加换行

二、实现方法

2.1 输入密码判断

首先有一个默认密码“123456”。将密码存储到一个数组中。接收到输入密码后,利用for循环,挨个比较串口接收数组中接收输入的密码是否与密码数组中密码相同。相同的话,提示“密码正确,已开门”。如果错误,累计错误次数,提示“密码错误,您还有*次输入机会”。如果三次输入任意一次正确,会将之前累计的错误次数清零。如果三次输入均错误,提示“三次密码错误,警报!”。此时,LED闪烁报警。

2.2 管理员模式

如果串口接收中断中接收到内容后,利用for循环,挨个对比指令是否为进入管理员模式指令。如果是进入管理员模式指令,返回“已进入管理员模式”,换行回车后显示“请输入管理员密码”。密码的判断方法与最开始的输入密码相同。

2.3 修改密码

进入管理员模式且正确输入密码后,可以修改密码。修改密码时,第一次输入后会首先拿新密码与原密码比较。如果新密码与原密码相同,返回“新密码请勿与原密码相同”。如果第二次输入密码后,判断与第一次的密码手抖相同。如果两次输入的密码相同,提示“密码修改成功”。然后自动退出管理员模式。

三、程序设计

3.1 输入密码判断

如果接收到的内容长度为六位,而且此时不是管理员模式。会对输入的密码进行判别。正确返回正确信息,错误提示错误信息。连续三系错误,提示报警。同时,LED闪烁。三次中任意一次输入正确,清零错误累计次数。程序设计如下

// 输入密码判断
void PassWord_Judge (void)
{
	u8 tempVar = 0;   // 临时循环变量
	u8 judgeRes = 0;   // 判别结果
	
	// 非管理员模式下输入密码
	if (gAdminFlag == 0 && gPassWordFlag == 1 && gPassWordChargeFlag == 0)
	{
		// for循环判断密码是否正确
		for (tempVar = 0;tempVar < 6;tempVar ++)
		{
			// 任意一位密码错误,就说明密码错误
			if (gReceFifo[tempVar] != gPassWord[tempVar])
			{
				judgeRes = 1;
			}
		}
		
		// 提示密码正确
		if (!judgeRes)
		{
			printf ("密码正确,已开门\r\n");
			gPassWordErrorCunt = 0;   // 清零密码错误计数变量
		}
		// 密码错误
		else
		{
			gPassWordErrorCunt = gPassWordErrorCunt + 1;   // 密码错误计数变量加1
			
			// 连续三次密码错误,报警
			if (gPassWordErrorCunt >= 3)
			{
				printf ("三次密码错误,警报!\r\n");
				gPassWordErrorCunt = 0;   // 清零密码错误计数变量
				
				// LED闪烁报警
				tempVar = 5;
				while (tempVar > 0)
				{
					Med_Led_StateReverse(LED1);   // LED闪烁
					delay_ms(200);
					tempVar --;
				}
			}
			else
			{
				printf ("密码错误,您还有%d次输入机会\r\n",3 - gPassWordErrorCunt);
			}
			
			judgeRes = 0;   // 清零判别结果
		}
		
		gPassWordFlag = 0;   // 清零输入密码标志位
		Clear_Rece();   // 清空接收数组
	}
	
	// 管理员模式下输入密码
	if (gAdminFlag == 1 && gPassWordFlag == 1 && gPassWordChargeFlag == 0)
	{
		// for循环判断密码是否正确
		for (tempVar = 0;tempVar < 6;tempVar ++)
		{
			// 任意一位密码错误,就说明密码错误
			if (gReceFifo[tempVar] != gAdminPassWord[tempVar])
			{
				judgeRes = 1;
			}
		}
		
		// 提示密码正确
		if (!judgeRes)
		{
			printf ("管理员密码正确\r\n");
			printf ("请输入新密码\r\n");
			gPassWordChargeFlag = 1;   // 修改密码标志位置1
		}
		else
		{
			printf ("管理员密码错误\r\n");
			judgeRes = 0;   // 清零判别结果
		}
		
		gPassWordFlag = 0;   // 清零输入密码标志位
		gAdminFlag = 0;   // 清零进入管理员模式标志位
		Clear_Rece();   // 清空接收数组
	}
}

密码判断有两种,一种是非管理员模式的密码判断,一种是管理员模式密码判断。编程时利用标志位进行了区分。

3.2 进入管理员模式

利用for循环,当接收内容长度为18(进入管理员模式指令加回车换行,共18个)时,判断指令是否与进入管理员指令相同。以此来判断是否需要进入管理员模式。程序设计如下

/*
 *==============================================================================
 *函数名称:Uart_Rece_Pares
 *函数功能:解析串口接收内容
 *输入参数:无
 *返回值:无
 *备  注:无
 *==============================================================================
 */
extern u8 gAdminFlag;   // 进入管理员模式标志位
extern u8 gPassWordFlag;   // 输入为密码的标志位
void Clear_Rece (void);   // 清空串口接收数组

u8 gAdminMode[16] = "Enter Admin Mode";

void Uart_Rece_Pares(void)   // 串口接收内容解析函数
{
	u8 tempVar = 0;   // 临时循环变量
	
	// 接收内容长度为6
	if (gReceCount == 8)
	{
		gPassWordFlag = 1;   // 接收内容为密码
	}
	// 接收到进入管理员模式指令
	else if (gReceCount == 18)
	{
		for (tempVar = 0;tempVar < 16;tempVar ++)
		{
			// 错误指令
			if (gReceFifo[tempVar] != gAdminMode[tempVar])
			{
				printf ("Error!\r\n");
			}
		}
		
		printf ("已进入管理员模式\r\n");
		printf ("请输入管理员密码\r\n");
		// 进入管理员模式标志位置1
		gAdminFlag = 1;
		Clear_Rece();   // 清空接收内容
	}
	// 错误指令
	else
	{
		printf ("Error!\r\n");
		Clear_Rece();   // 清空接收内容
	}
}

这里把判断是否为输入密码的程序也加进来了,比较简单,就不再单独介绍了。

3.3 修改密码

修改密码只需要定义一个数组用来接收新密码。第一次接收到新密码后,与原密码对比。如果与原密码相同,返回对应信息。如果不同,提示“请再次输入新密码”。然后再拿接收数组中的新输入密码与第一次输入的密码对比,相同提示“密码修改成功”。程序设计如下

// 修改密码
void PassWord_Charge (void)
{
	u8 tempVar = 0;   // 临时循环变量
	u8 judgeRes = 0;   // 判别结果
	
	// 第一次输入新密码
	if (gPassWordChargeFlag == 1 && gPassWordFlag == 1)
	{
		// for循环判断新密码是否与原密码相同
		for (tempVar = 0;tempVar < 6;tempVar ++)
		{
			if (gReceFifo[tempVar] != gPassWord[tempVar])
			{
				judgeRes = 1;
			}
		}
		
		// 新密码与原密码相同
		if (!judgeRes)
		{
			printf ("新密码请勿与原密码相同\r\n");
			judgeRes = 0;   // 清零判别结果
		}
		else
		{
			// for循环用新密码覆盖原密码
			for (tempVar = 0;tempVar < 6;tempVar ++)
			{
				gPassWord[tempVar] = gReceFifo[tempVar];
			}
			gPassWordChargeFlag = 2;   // 标志位变为2,提示下一次准备再次确认新密码
			printf ("请再次输入新密码\r\n");
		}
		
		gPassWordFlag = 0;   // 清零输入密码标志位
		Clear_Rece();   // 清空接收数组
	}
	
	// 第二次输入新密码
	if (gPassWordChargeFlag == 2 && gPassWordFlag == 1)
	{
		// for循环判断新密码是否与上次输入的新密码相同
		for (tempVar = 0;tempVar < 6;tempVar ++)
		{
			if (gReceFifo[tempVar] != gPassWord[tempVar])
			{
				judgeRes = 1;
			}
		}
		
		// 连续两次输入新密码相同
		if (!judgeRes)
		{
			printf ("密码修改成功\r\n");
			gPassWordChargeFlag = 0;   // 清零修改密码标志位
		}
		else
		{
			printf ("连续两次输入密码不同,请重新输入\r\n");
		}
		
		gPassWordFlag = 0;   // 清零输入密码标志位
		Clear_Rece();   // 清空接收数组
	}
}

四、问题总结

4.1 输入内容一直提示Error

这个原因是清除接收数组的位置不对。在while(1)轮询中有一个清除接收数组,导致还未进行判断,接收内容就已经被清除。清除接收数组内容,一定要放在每一个if判断里面,而不能放在外面。

4.2 密码判断一直错误

原因是程序中存储密码的数组定义错误。最开始的定义方法如下

u8 gPassWord[6] = {1,2,3,4,5,6};   // 密码,初始为123456
u8 gAdminPassWord[6] = {1,4,7,2,5,8};   // 管理员密码,147258

这么定义,数组中的每一位数就是数字,而不是字符。如果想定义成字符,应该像下面这样定义

u8 gPassWord[6] = {'1','2','3','4','5','6'};   // 密码,初始为123456
u8 gAdminPassWord[6] = {'1','4','7','2','5','8'};   // 管理员密码,147258

五、成果展示

5.1 输入密码判断

输入密码判断
密码错误报警

5.2 进入管理员模式

进入管理员模式

5.3 修改密码

修改密码

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

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

相关文章

Lua,不使用模块,解压文件

本来lua遍历文件夹下压缩包内容、路径可以通过加载模块&#xff1a; require(“lfs”) 和 require(“zip”) 来解决。 但是本人通过c调用lua时&#xff0c;只要lua脚本中使用require加载模块&#xff0c;就会出错。 因此为了能够让c通过lua&#xff0c;解压当前路径下压缩包&a…

【基础算法】回溯算法相关题目

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招算法的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于代码随想录进行的&#xff0c;每个算法代码参考leetcode高赞回答和…

Android RecyclerView AsyncListUtil手动刷新fillData,kotlin

Android RecyclerView AsyncListUtil手动刷新fillData&#xff0c;kotlin implementation com.github.bumptech.glide:glide:4.15.1implementation androidx.constraintlayout:constraintlayout:1.1.3 import android.os.Bundle import android.util.Log import android.view.V…

百万连接实现02:使用epoll实现的服务器

使用的操作系统&#xff1a; t$ cat /proc/version Linux version 4.19.260 (lkmaoubuntu) (gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.12)) #1 SMP Thu Sep 29 14:19:07 CST 2022 文件句柄的限制 如果不修改连接测试&#xff0c;会报错 一个tcp连接就需要…

北京大学2015计算机学科夏令营上机考试

目录 A:整数的个数 B:过滤多余的空格 C:二维数组右上左下遍历 D 合影效果 E:Simple prefix compression【做不起】 F:To Europe! To Europe!【做不起】 G:The Game【做不起】 H:Falling Leaves A:整数的个数 #include<iostream> using namespace std; int main(…

VSCode 免安装及中文设置

前言&#xff1a;VSCode作为目前最强大的文本编辑器&#xff0c;通过内部的插件市场可满足各种开发需求。使用免安装版可以自定义插件安装位置等&#xff0c;而使用安装包安装只能通过修改快捷方式自定义&#xff0c;十分不方便。因此这里分享如何安装免安装版的VSCode。 下载…

ETL是什么?怎样更快的学习ETL?

ETL是英文Extract-Transform-Load的缩写&#xff0c;用来描述将数据从源端经过抽取(extract)、转换(transform)、加载(load)至目的端的过程&#xff0c;它能够对各种分布的、异构的源数据(如关系数据)进行抽取&#xff0c;按照预先设计的规则将不完整数据、重复数据以及错误数据…

滤波后点云的个数和之前相同,只是有的点云坐标是nan

进行点云的条件滤波&#xff0c;滤波前后点云的个数不变&#xff0c;只是被滤掉的点坐标显示为nan。代码片段如下&#xff1a; pcl::ConditionAnd<pcl::PointXYZ>::Ptr range_cond(new pcl::ConditionAnd<pcl::PointXYZ>()); range_cond->addComparison(pcl::Fi…

李宏毅transformer讲解;B站内测“搜索AI助手”功能

&#x1f989; AI新闻 &#x1f680; B站内测“搜索AI助手”功能 摘要&#xff1a;据反馈&#xff0c;B站正在内测“搜索 AI 助手”功能。用户在搜索框内输入问句或在搜索词中添加“?”即可体验此新功能。截图显示&#xff0c;该功能会为用户的搜索提供一个生成的答案&#…

hcip作业二

实验要求&#xff1a; 要求&#xff1a;R1-R2-R3-R4-R5 RIP 100运行版本2&#xff1b;R6-R7 RIP 200 运行版本1 1.使用合理IP地址规划网络&#xff0c;各自创建环回接口 2.R1创建环回 172.16.1.1/24 172.16.2.1/24 172.16.3.1/24 3.要求R3使用R2访问R1环回 4.减少路由条目数量&…

盘点一个Python网络爬虫抓取股票代码问题(上篇)

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 去来江口守空船&#xff0c;绕船月明江水寒。 大家好&#xff0c;我是皮皮。 一、前言 前几天在Python白银群【厚德载物】问了一个Python网络爬虫的问题…

新手入门深度学习 | 3-2:激活函数activation

一、什么是激活函数 生物神经网络启发了人工神经网络(ANN)的发展。但是,人工神经网络并非大脑运作的近似表示。不过在我们了解为什么在人工神经网络中使用激活函数之前,先了解生物神经网络与激活函数的相关性是很有用处的。 典型神经元的物理结构包括细胞体(cell body)、…

软件的兼容性测试确保良好稳定运行的用户体验

在数字化时代&#xff0c;各种软件应用的开发和推广越来越普遍。然而&#xff0c;由于不同的操作系统、不同的设备配置和不同的软件版本&#xff0c;软件的兼容性成为了一个重要的问题&#xff0c;可以说软件的兼容性测试确保良好稳定运行的用户体验。 首先&#xff0c;软件的兼…

MySQL Optimization Learning(三)

一、通过索引进行优化 数据结构 Data Structure Visualizations 数据可视化效果展示 Binary Search Tree 插入数据可视化效果展示 AVL Tree Red/Black Tree --MYISAM存储引擎数据和引用分开存储 DROP TABLE IF EXISTS t_test; CREATE TABLE t_test (id int(11) NOT NULL,…

websocket 发送的消息超过默认限制就会自动断开连接

springboot集成websocket需要三步&#xff1a; 添加依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId><version>2.1.6.RELEASE</version></dependency>…

【GIT】Git常用命令学习

Git常用命令学习 说明&#xff1a;<>表示占位符的说明&#xff0c;[]表示可选&#xff0c;/表示“或” 仓库操作 初始化创建一个本地仓库 git init克隆远程仓库至本地 git clone <远程仓库地址> [仓库名称] #可以加上自定义仓库名称配置仓库 git config user.name…

Linux的动静态库

动静态库 1. 见一见动静态库2. 动静态库概念2.1 为什么要有动静态库2.2 定义 3. 写一写——库的设计角度打包成静态库打包成动态库 4. 用一用——使用者角度4.1 直接使用头文件和源文件&#xff08;直接给源代码&#xff09;4.2 得到头文件和源文件进过处理后形成的二进制文件.…

C++ - 20230703

一. 思维导图 二.练习 全局变量&#xff0c;int monster 10000;定义英雄类hero&#xff0c;受保护的属性string name&#xff0c;int hp,int attck&#xff1b;公有的无参构造&#xff0c;有参构造&#xff0c;虚成员函数 void Atk(){blood-0;}&#xff0c;法师类继承自英雄类…

SpringCloud:微服务技术

一、认识微服务&#xff1a; 首先&#xff0c;微服务架构不等于SpringCloud&#xff0c;微服务架构是一种经过良好架构设计的分布式架构方案&#xff0c; &#xff0c;它将应用构建成一系列按业务领域划分模块的&#xff0c;小的自治服务&#xff0c;并解决服务拆分所产生的各种…