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

文章目录

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


一、功能简介

本项目使用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

【STM32单片机】多功能电子密码锁设计_第1张图片
【STM32单片机】多功能电子密码锁设计_第2张图片

【STM32单片机】多功能电子密码锁设计_第3张图片

【STM32单片机】多功能电子密码锁设计_第4张图片


联系作者

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

你可能感兴趣的:(单片机,stm32,嵌入式硬件,proteus)