【STM32单片机】多功能电子密码锁设计

news2024/10/7 14:28:50

文章目录

  • 一、功能简介
  • 二、软件设计
  • 三、实验现象
  • 联系作者


一、功能简介

本项目使用STM32F103C8T6单片机控制器,使用按键、IIC OLED模块、DS18B20温度传感器、SG90舵机、红外遥控、矩阵按键、EEPROM等。
主要功能:
系统运行后,OLED显示RTC日期时间和温度;

键盘解锁:可使用矩阵键盘S1-S10键输入数字
0-9,初始密码为012345,当密码输入有误可按下S11键撤回,输入完成后可按下S12键解锁,若密码正确则开锁,舵机启动。若密码错误,OLED显示错误信息,当错误次数超过3次则锁死一段时间后重新输入。当按下S13键可修改密码,进入密码修改界面首先需校验旧密码,当输入旧密码正确,才可进入新密码设置。可按下S16键返回主界面。密码支持掉电不丢失。

红外遥控解锁:使用红外遥控器,按下第一个键(该键对应HEX为A2),则一键解锁。


二、软件设计

/*
作者:嗨小易(QQ:3443792007)

*/



//系统参数初始化
void sys_parm_init(void)
{
	u8 i=0;
	sys_ctrl.mode=0;
	sys_ctrl.err_cnt=0;
	sys_ctrl.psw_flag=0;
	sys_ctrl.psw_resive=0;
	sys_ctrl.psw_bit=0;
	//初始密码0-5
	if(AT24CXX_ReadOneByte(255)!=0x28)
	{
		AT24CXX_WriteOneByte(255,0x28);
		//写入初始密码到EEPROM
		for(i=0;i<PSW_BITNUM;i++)
		{
			sys_ctrl.save_psw[i]=i;
			AT24CXX_WriteOneByte(i,sys_ctrl.save_psw[i]);
		}	
	}
	else
	{
		//读取EEPROM内密码数据
		for(i=0;i<PSW_BITNUM;i++)
		{
			sys_ctrl.save_psw[i]=AT24CXX_ReadOneByte(i);	
		}	
	}	
}

//系统时钟温度显示模块
void sys_rtc_temp_show(void)
{
	u8 buf[5];
	static u8 i=0;

	OLED_Clear();
	OLED_ShowString(0,0,  "2023-08-22 Week5",16);
	OLED_ShowString(0,20, "   12:16:56",16);
	OLED_ShowString(0,40,"  Temp:    C",16);
	
	while(sys_ctrl.mode==0)
	{
		//温度获取
		i++;
		if(i%1==0)
			sys_ctrl.temp=DS18B20_GetTemperture()*10;
		//日期显示
		buf[0]=calendar.w_year/1000+0x30;
		buf[1]=calendar.w_year%1000/100+0x30;
		buf[2]=calendar.w_year%1000%100/10+0x30;
		buf[3]=calendar.w_year%1000%100%10+0x30;
		buf[4]='\0';
		OLED_ShowString(0,0,buf,16);
		
		buf[0]=calendar.w_month/10+0x30;
		buf[1]=calendar.w_month%10+0x30;
		buf[2]='\0';
		OLED_ShowString(5*8,0,buf,16);
		buf[0]=calendar.w_date/10+0x30;
		buf[1]=calendar.w_date%10+0x30;
		buf[2]='\0';
		OLED_ShowString(8*8,0,buf,16);
		buf[0]=calendar.week%7+0x30;
		buf[1]='\0';
		OLED_ShowString(15*8,0,buf,16);
		
		//时间显示
		buf[0]=calendar.hour/10+0x30;
		buf[1]=calendar.hour%10+0x30;
		buf[2]='\0';
		OLED_ShowString(3*8,20,buf,16);//时
		buf[0]=calendar.min/10+0x30;
		buf[1]=calendar.min%10+0x30;
		buf[2]='\0';
		OLED_ShowString(6*8,20,buf,16);//分
		buf[0]=calendar.sec/10+0x30;
		buf[1]=calendar.sec%10+0x30;
		buf[2]='\0';
		OLED_ShowString(9*8,20,buf,16);//秒
		
		//温度显示
		buf[0]=sys_ctrl.temp/100+0x30;
		buf[1]=sys_ctrl.temp%100/10+0x30;
		buf[2]='.';
		buf[3]=sys_ctrl.temp%100%10+0x30;
		buf[4]='\0';
		OLED_ShowString(7*8,40,buf,16);
		
		//检测是否按下键,进入密码输入界面
		if(KEY_Matrix_Scan()!=0)
		{
			sys_ctrl.mode=1;
			break;
		}
		OLED_Refresh_Gram();//刷新显存
	}
}

//密码输入界面显示
void psw_input_show(void)
{
	OLED_Clear();
	OLED_ShowString(0,0,"Password:",16);
}
//修改密码时输入校验密码界面显示
void adjust_input_show(void)
{
	OLED_Clear();
	OLED_ShowString(0,0,"Calib Psw:",16);
}
//设置新密码界面显示
void set_new_psw_show(void)
{
	OLED_Clear();
	OLED_ShowString(0,0,"New Psw:",16);	
}
//一键解锁界面显示
void one_click_unlock_show(void)
{
	OLED_Clear();
	OLED_ShowString(0,0,"One click unlock",16);
	OLED_ShowString(0,20,"OK...",16);	
}

//修改密码时,密码校验
void sys_psw_resive(void)
{
	u8 key=0;
	//在密码设置有效
	if(sys_ctrl.psw_resive)
	{
		//初始化参数值
		sys_ctrl.psw_bit=0;
		sys_ctrl.err_cnt=0;
		sys_ctrl.psw_flag=0;
		memset(sys_ctrl.psw,0,PSW_BITNUM);//清除输入数据
	
		adjust_input_show();//修改密码时输入校验密码界面显示
	
		while(sys_ctrl.psw_resive)
		{
			//键盘扫描
			key=KEY_Matrix_Scan();
			if(key>0)//按键输入
			{
				BEEP_Alarm(100,100);//提示音
				if(key<=10)//数字键0-9
				{
					if(sys_ctrl.psw_bit<PSW_BITNUM)//最多输入密码位数
					{
						sys_ctrl.psw[sys_ctrl.psw_bit]=key-1;//记录输入密码
						sys_ctrl.psw_bit++;//输入位数累加
						//密码可见
						if(PASSWORD_SHOW_HIDE)
							//显示输入密码
							OLED_ShowNum((9+sys_ctrl.psw_bit)*8,0,sys_ctrl.psw[sys_ctrl.psw_bit-1],1,16);
						//密码不可见
						else
							OLED_ShowString((9+sys_ctrl.psw_bit)*8,0,"*",16);
					}	
				}
				else if(key==11)//撤回键
				{
					sys_ctrl.psw[sys_ctrl.psw_bit-1]=10;//将所需撤回的数据设置为无效数
					OLED_ShowString((9+sys_ctrl.psw_bit)*8,0," ",16);//将撤销位置显示空位
					sys_ctrl.psw_bit--;
					if(sys_ctrl.psw_bit<0)sys_ctrl.psw_bit=0;
				}
				else if(key==12)//确定键
				{
					sys_ctrl.psw_flag=0;
					sys_ctrl.psw_bit=0;
					//输入密码与存储密码比较
					if(memcmp(sys_ctrl.psw,sys_ctrl.save_psw,PSW_BITNUM)==0)
						sys_ctrl.psw_flag=1;//密码正确
					memset(sys_ctrl.psw,0,PSW_BITNUM);//清除输入数据	
		
					//密码正确,开锁
					if(sys_ctrl.psw_flag==1)
					{
						sys_ctrl.err_cnt=0;
						OLED_ShowString(0,20,"Password OK!   ",16);
						OLED_Refresh_Gram();//刷新显存
						delay_ms(1000);
						break;//进入新密码设置程序	
					}
					//如果密码错误
					else
					{
						sys_ctrl.err_cnt++;//错误次数累计
						OLED_ShowString(0,20,"Password Error!",16);
						OLED_Refresh_Gram();//刷新显存
						//密码输入错误次数超限
						if(sys_ctrl.err_cnt>=ERROR_PASSWORD_CNT)
						{
							sys_ctrl.err_cnt=0;
							OLED_ShowString(0,0,"Too many errors!",16);
							OLED_ShowString(0,20,"Please wait...",16);
							OLED_Refresh_Gram();//刷新显存
							delay_ms(1000);	
							delay_ms(1000);
							delay_ms(1000);
						}
						else delay_ms(1000);
						adjust_input_show();//修改密码时输入校验密码界面显示
					}
				}
				else if(key==16)//退出键
				{
					sys_ctrl.psw_resive=0;
					sys_ctrl.mode=0;//回到时钟温度显示模式	
					break;	
				}
			}
			
			OLED_Refresh_Gram();//刷新显存
		}		
	}	
}


//应用控制系统
void app_sys_ctrl_demo(void)
{
	u8 i=10;
	
	LED_Init();
	USART1_Init(115200);
	AT24CXX_Init();
	OLED_Init();
	KEY_Matrix_Init();
	BEEP_Init();
	DS18B20_Init();
	RTC_Init();
	Hwjs_Init();
	//获取稳定数据
	while(i--)
	{
		sys_ctrl.temp=DS18B20_GetTemperture()*10;
		delay_ms(100);
	}
	TIM4_Init(200,36000-1);  //定时100ms
	TIM3_CH2_PWM_Init(20000-1,71); //周期20ms
	steer_control(0);
	sys_parm_init();//系统参数初始化
	
	while(1)
	{
		sys_rtc_temp_show();//系统时钟温度显示模块
		sys_psw_unlock_show();//系统解锁显示模块
		sys_psw_resive();//修改密码时,密码校验
		sys_new_psw_set();//新密码设置
	}
}





三、实验现象

B站演示视频:https://space.bilibili.com/444388619

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


联系作者

专注于51单片机、STM32、国产32、DSP、Proteus、ardunio、ESP32、物联网软件开发,PCB设计,视频分享,技术交流。

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

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

相关文章

【前段基础入门之】=>CSS3的新增特性!

文章目录 CSS3概述CSS3私有前缀常见浏览器私有前缀 新增盒模型相关属性怪异盒模型拖拽调整盒子大小盒子阴影不透明度 新增背景属性background-originbackground-clipbackground-size多背景图backgorund 复合属性 新增边框属性边框圆角边框外轮廓 新增文本属性文本阴影文本换行文…

用合成数据训练车辆姿态估计神经网络

我们的客户希望开发一款应用程序&#xff0c;引导用户通过 AR 指南和自动照片拍摄来拍摄更高质量的汽车照片。 本文重点介绍构建汽车姿态估计组件的技术。 在应用程序中&#xff0c;用户被引导站在与汽车一定的角度和距离&#xff0c;以标准化的方式捕捉最好的照片。 当用户处于…

1600*C. Good Subarrays(找规律前缀和)

Problem - 1398C - Codeforces 解析&#xff1a; 可以写出 sum[ j ] - sum[ i ] j - i 1&#xff0c;对其移项得 sum[ j ] - j sum[ i ] - &#xff08;i - 1&#xff09;&#xff0c;问题转换为有多少个前缀和相等&#xff0c;则用map遍历统计一遍即可。 注意&#xff0c;当…

QMC5883L-磁力计椭球拟合校准

1.概述 磁力计椭球拟合校准是一种将磁力计测量数据校准到真实磁场的技术。这种技术通常使用椭球模型来拟合磁力计的测量结果&#xff0c;然后通过最小二乘法来找到拟合参数的最优解。 2.总体思想 磁力计椭球拟合校准的思想包括以下几个步骤&#xff1a; 1.数据预处理&#x…

Java 21 新功能展示(含示例)

Java 21 于 2023 年 9 月 19 日发布&#xff0c;是 Oracle 标准 Java 实现的下一个长期支持&#xff08;LTS&#xff09;版本。Java 21 具有以下 15 项功能。 字符串模板&#xff08;预览版&#xff09; [JEP-430] 序列集合 [JEP-431] 代 ZGC [JEP-439&#xff3d; 记录模式…

Helm部署EMQX集群

端口说明&#xff1a; 端口说明集群内端口Nodeport备注mqtt188331274Port for MQTTmqttssl888331170Port for MQTT(SSL)mgmt8081无ws808330099Port for WebSocket/HTTPwss808432580Port for WSS/HTTPSdashboard1808331303Port for dashboard 一、Helm在线部署EMQX集群 1、安…

Compose输入框

TextField label设置提示内容&#xff0c;TextFieldDefaults.textFieldColors设置输入框背景颜色 TextField(modifier Modifier.fillMaxWidth().padding(5.dp),value text.value,onValueChange { text.value it },label { Text(text "请输入内容") },colors …

算法题:买卖股票的最佳时机 II

这道题是贪心算法的中级难度练习题&#xff0c;由于题目设定&#xff0c;整个价格都是透明的&#xff0c;这里并不涉及需要预测股票涨势的问题。解决思路不难&#xff0c;就是一旦股票价格开始下降了就买入&#xff0c;一旦上升了&#xff0c;就赶紧卖出。&#xff08;完整题目…

led护眼台灯对眼睛有伤害吗?推荐好用的led护眼台灯

其实led护眼台灯对眼睛伤害是不大的&#xff0c;而且和白炽灯、卤素灯等老式台灯相对比&#xff0c;反而更加护眼。因为白炽灯、卤素灯等光线都不太稳定&#xff0c;而且光线不是很均匀可以明显感觉有明暗差&#xff0c;最主要的是频闪现象会比较严重&#xff0c;长时间使用的话…

Apache Tomcat安装、运行

介绍 Apache Tomcat是下面多个规范的一个开源实现&#xff1a;Jakarta Servlet、Jakarta Server Pages、Jakarta Expression Language、Jakarta WebSocket、Jakarta Annotations 和 Jakarta Authentication。这些规范是 Jakarta EE 平台的一部分。 Jakarta EE 平台是Java EE平…

Vue Router的使用

使用 项目中注入路由器 在项目中 src 目录下新建 router 目录&#xff0c;其中包含 index.js 路由主文件。 // src/router/index.jsimport Vue from vue import Router from vue-router import { routes } from ./routes.jsVue.use(Router) const router new Router({route…

EPDB 08、EPDBS 10、PDRV、EPDZA06插装式比例减压阀放大器

比例方向阀W42E-5PS03、W43E-5PS05、W42E-1AS06、W43E-1AS06、插装式S22E-1V08放大器。 该放大器既可用于工业及移动设备应用&#xff0c;也可用于固定安装。因此&#xff0c;电压范围非常宽&#xff0c;在8至35VDC之间变化。这些放大器对欠压和电压尖峰非常不敏感&#xff0c…

浅谈时间流管理体系

不想聊技术&#xff0c;但又想分享一些东西&#xff0c;这篇文章分享下如何构造自己的时间流管理体系以及如何完整的把控一个事件安排统筹&#xff0c;这里对一个大型事件或大型知识体系如何分解为不同问题的小点不做点出&#xff0c;这里只提时间管理体系化。 好处的话也不做阐…

Nginx+Keepalived实现服务高可用

Nginx 和 Keepalived 是常用于构建高可用性&#xff08;High Availability&#xff09;架构的工具。Nginx 是一款高性能的Web服务器和反向代理服务器&#xff0c;而Keepalived则提供了对Nginx服务的健康状态监测和故障切换功能。 下载Nginx 在服务器1和服务器2分别下载nginx …

深入理解 python 虚拟机:原来虚拟机是这么实现闭包的

深入理解 python 虚拟机&#xff1a;原来虚拟机是这么实现闭包的 在本篇文章当中主要从虚拟机层面讨论函数闭包是如何实现的&#xff0c;当能够从设计者的层面去理解闭包就再也不用死记硬背一些闭包的概念了&#xff0c;因为如果你理解闭包的设计原理之后&#xff0c;这些都是…

嵌入式学习笔记(48)什么是I2C通信

10.1.1物理接口&#xff1a;SCL SDA (1)SCL&#xff1a;时钟线&#xff0c;传输CLK&#xff0c;一般是I2C主设备向从设备提供时钟的通道。 (2)SDA&#xff1a;数据线&#xff0c;通信数据都通过SDA线传输。 10.1.2通信特征&#xff1a;串行、同步、非差分、低速 (1)I2C属于…

Python中的多态

迷途小书童 读完需要 3分钟 速读仅需 1 分钟 当我们谈到多态时&#xff0c;可以将其比喻为一个人具有多种身份的能力。在不同的情境下&#xff0c;这个人可以表现出不同的行为和特征。在 Python 中&#xff0c;多态是面向对象编程中的一个重要概念&#xff0c;它允许我们使用相…

PHP 伪协议:使用 php://filter 为数据流应用过滤器

文章目录 参考环境PHP 伪协议概念为什么需要 PHP 伪协议&#xff1f; php://filter概念格式 基本使用普通读写file_get_contents 与 file_put_contentsinclude 过滤器的基本使用base64 的编码与解码rot13 加解密rot13 算法string.rot13 过滤器列表多个过滤器的使用注意事项 处理…

【软件测试】功能测试/接口测试/自动化测试/性能测试/验收测试

软件测试的主要流程 一、测试主要的四个阶段 1.测试计划设计阶段&#xff1a;产品立项之后&#xff0c;进行需求分析&#xff0c;需求评审&#xff0c;业务需求评级&#xff0c;绘制业务流程图。确定测试负责人&#xff0c;开始制定测试计划&#xff1b; 2.测试准备阶段&…