基于STC15单片机的智能密码锁(矩阵按键输入)设计

这篇具有很好参考价值的文章主要介绍了基于STC15单片机的智能密码锁(矩阵按键输入)设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

一、项目背景

二、功能需求

 三、功能组成

四、总结


一、项目背景

        智能门锁是一种基于现代智能化技术,与传统门锁进行比较的创新型的电子门锁产品。传统门锁通常采用钥匙旋转来开启门锁,但传统门锁存在钥匙遗失、易被复制等问题,特别是具有主动性质的人员如不法分子,可以通过主动窃取、复制钥匙等手段,轻松翻越传统门锁,进入家庭、企事业单位或其他场所,造成不必要的经济和社会损失。智能门锁则通过密码、指纹、身份验证等技术,提供更加安全、便捷、舒适的门锁体验,实现智能门锁物联网系统。

        智能门锁结合了多个技术:如无线通信技术、计算机技术、集成电路技术和自动控制技术等。同时在保证安全性的前提下,实现开锁过程的智能和自动化。

        智能门锁是现代化、智能化、人性化、网络化、绿色化、安全性齐备的新型门锁产品,得到越来越多人的青睐和使用。

二、功能需求

智能门锁的核心功能是使用数字密码进行解锁,另外还加入密码修改功能以及对密码错误次数过多的报警和禁止操作功能。

单片机智能密码锁,单片机,嵌入式硬件,c语言,51单片机

在功能上需要有欢迎界面,主界面的时间显示,以及在按键按下时可以自由切换界面,主要有界面一为输入密码界面,界面二为更改密码界面。 

 三、功能组成

        在功能实现过程中需要用到LCD1602来显示,首先我们需要对LCD1602进行初始化,其次呢,还要用到LCD1602的显示功能,在智能锁的开机界面我们想让它来显示我们设置字符串,首先就要用到字符串显示函数

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]);
	}
}

通过这个函数,我们就可以在LCD屏的指定位置开始显示我们指定的字符串,同时考虑到,在我们输入密码的过程中,密码是通过在屏幕上一个一个显示,所以我们还需要一个可以在指定位置来显示单个字符的函数

void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

此外LCD1602还为我们预留了8个可以存放自定义字符的地址,我们可以通过取模软件来自定义自己想要显示的字符,那我们要如何来显示呢,这时就要用到下面这个函数了

/**
  * @brief	在指定位置显示自定义字符
*   @param	X 列0~15; Y 行 0~1; Num 字符存储位置0~7;*LCD_Cust 自定义字模表
  * @retval	
  */
void LCD_Show_Customer(unsigned char X,unsigned char Y,unsigned char Num,unsigned char *LCD_Cust)//
{
	unsigned char i;
	unsigned char Com = Num;
	X&=0X0F;
	Y&=0X01;
	if(Y)
	{
		X=X+0X40;
	}
	X=X+0X80;
	Com=Com<<3;
	Com=Com+0X40;
	for(i=0;i<8;i++) 
	{
		LCD_WriteCommand(Com);
		Com++;
		LCD_WriteData(LCD_Cust[i]);
	}
	LCD_WriteCommand(X);
	LCD_WriteData(Num);
}

在第一节我们知道,在上电后,我们不仅想让它只有欢迎界面,还希望它可以在我们没有操作的时候显示当前时间,年月日时分秒等等,为了时间的准确性,我们就需要用到时钟芯片,既RTC芯片(Real-Time Clock Chip),RTC芯片可以提供实时时钟功能,多用于需要记录时间信息的场合,如计时器、闹钟、烤箱等等。常用的RTC芯片有DS1302、DS3231、PCF8583等,此次我们使用PCF8583,对PCF8583进行配置后,我们就要让我们设定的时间可以显示在LCD屏幕上,通过前面的两个函数,我们就可以轻松实现这个功能

void LCD_Display_Main(unsigned char Lock_Flag)
{
	unsigned char time_ge,time_shi;
	get_time();
	if(Lock_Flag == 0)
	{
		Lock(0);
	}
	else
	{
		Lock(1);
	}
	time_ge=time_buf1[1]%10;
	time_shi=time_buf1[1]/10;
	LCD_ShowChar(1,2,'2');
	LCD_ShowChar(1,3,'0');
	LCD_ShowChar(1,5,time_shi+'0');
	LCD_ShowChar(1,6,time_ge+'0');

	time_ge=time_buf1[2]%10;
	time_shi=time_buf1[2]/10;
	LCD_ShowChar(1,8,time_shi+'0');
	LCD_ShowChar(1,9,time_ge+'0');

	time_ge=time_buf1[3]%10;
	time_shi=time_buf1[3]/10;
	LCD_ShowChar(1,11,time_shi+'0');
	LCD_ShowChar(1,12,time_ge+'0');

	time_ge=time_buf1[4]%10;
	time_shi=time_buf1[4]/10;
	LCD_ShowChar(2,4,time_shi+'0');
	LCD_ShowChar(2,5,time_ge+'0');

	time_ge=time_buf1[5]%10;
	time_shi=time_buf1[5]/10;
	LCD_ShowChar(2,7,time_shi+'0');
	LCD_ShowChar(2,8,time_ge+'0');

	time_ge=time_buf1[6]%10;
	time_shi=time_buf1[6]/10;
	LCD_ShowChar(2,10,time_shi+'0');
	LCD_ShowChar(2,11,time_ge+'0');
	


	LCD_ShowChar(1,14,time_buf1[7]+'0');
	

	
	LCD_Show_Customer(3,0,2,table3);
	LCD_Show_Customer(6,0,2,table3);
	LCD_Show_Customer(9,0,2,table3);
	
	LCD_Show_Customer(5,1,3,table4);
	LCD_Show_Customer(8,1,3,table4);
	

在前面我们提到密码的输入需要通过矩阵按键来进行输入,这就要用到我们对按键扫描的知识了,话不多说直接放代码

unsigned char Matrixkey()
{
	unsigned char KeyNumber=0;
	P2M1&=0X00;P2M0|=0X00;
	P4M1&=0X00;P4M0|=0X00;
	P5M1&=0X00;P5M0|=0X00;
	P44=1;P45=1;P46=1;P47=1;P26=1;P27=1;P52=1;P53=1;
	P44=0;
	if(P52==0){Delay(20);while(P52==0);Delay(20);KeyNumber=1;}
	if(P53==0){Delay(20);while(P53==0);Delay(20);KeyNumber=2;}
	if(P26==0){Delay(20);while(P26==0);Delay(20);KeyNumber=3;}
	if(P27==0){Delay(20);while(P27==0);Delay(20);KeyNumber=4;}
	P44=1;P45=1;P46=1;P47=1;P26=1;P27=1;P52=1;P53=1;
	P45=0;
	if(P52==0){Delay(20);while(P52==0);Delay(20);KeyNumber=5;}
	if(P53==0){Delay(20);while(P53==0);Delay(20);KeyNumber=6;}
	if(P26==0){Delay(20);while(P26==0);Delay(20);KeyNumber=7;}
	if(P27==0){Delay(20);while(P27==0);Delay(20);KeyNumber=8;}
	P44=1;P45=1;P46=1;P47=1;P26=1;P27=1;P52=1;P53=1;
	P46=0;
	if(P52==0){Delay(20);while(P52==0);Delay(20);KeyNumber=9;}
	if(P53==0){Delay(20);while(P53==0);Delay(20);KeyNumber=10;}
	if(P26==0){Delay(20);while(P26==0);Delay(20);KeyNumber=11;}
	if(P27==0){Delay(20);while(P27==0);Delay(20);KeyNumber=12;}
	P44=1;P45=1;P46=1;P47=1;P26=1;P27=1;P52=1;P53=1;
	P47=0;
	if(P52==0){Delay(20);while(P52==0);Delay(20);KeyNumber=13;}
	if(P53==0){Delay(20);while(P53==0);Delay(20);KeyNumber=14;}
	if(P26==0){Delay(20);while(P26==0);Delay(20);KeyNumber=15;}
	if(P27==0){Delay(20);while(P27==0);Delay(20);KeyNumber=16;}
	return KeyNumber;
}

关于矩阵键盘的详细内容可以参考以前的文章哦~

PS:在矩阵按键那一节有详细介绍和实现原理~

到这里我们已经基本完成了对外设的配置,但是我们怎么来模拟开锁和关锁呢,可能大家已经想到可以使用舵机等等,这次呢我们就使用步进电机的正转和反转来模拟关锁和开锁,要想使用步进电机,首先就要对步进电机进行配置,我们可以使用单四拍


void Motor_Drive41(uchar X,uint Speed)
{
  if(X==1)  
	{
		DD=0;CC=0;BB=0;AA=1;	
    Delay(Speed);  

		DD=0;CC=0;BB=1;AA=0;	
    Delay(Speed);  

		DD=0;CC=1;BB=0;AA=0;	
    Delay(Speed);  

		DD=1;CC=0;BB=0;AA=0;	
    Delay(Speed); 
  }
	else       
	{
		DD=1;CC=0;BB=0;AA=0;	
    Delay(Speed);  

		DD=0;CC=1;BB=0;AA=0;	
    Delay(Speed);  

		DD=0;CC=0;BB=1;AA=0;	
    Delay(Speed); 

		DD=0;CC=0;BB=0;AA=1;	
    Delay(Speed);  
  }	
}

电机既然要启动,我们就需要把电机关闭,要怎么实现呢

void MotorStop(void)
{
   DD=0;CC=0;BB=0;AA=0;
}

是的,就是这么简单。

终于到这里我们完成了对外设的配置,下一步就要来编写我们的主函数

/*
1、	输入密码和更改密码后的确认按键(返回键值为13)
2、	输入密码和更改密码时的删除按键(返回键值为14)
3、	关锁键(返回键值为15)且只能在开锁状态下使用
4、	对矩阵按键扫描进行了优化(可避免因按键抖动造成的键值连续返回)
5、	按键按下蜂鸣器提醒
6、	开机音乐
7、	密码错误三次锁定三秒且蜂鸣器长鸣
8、	对功能进行了优化(关锁状态下不能进入密码更改界面,只能在开锁状态下才能进入密码更改界面,且开锁状态        
    下不能再次进入密码输入界面)
9、 按键16(返回键值16)切换界面,选择输入密码还是更改密码

  */
#include <STC15F2K60S2.H>
#include "LCD1602.h"
#include "Delay.h"
#include "Matrixkey.h"
#include "stepmotor.h"
#include "PCF8563.h"
#include "Start.h"
#include <string.h>

第一步我们需要对我们的基础功能进行介绍,并引入我们需要的函数头文件。

unsigned char Page_Flag;
unsigned char Lock_Flag;
unsigned char OK_Flag;
unsigned char Error_Num;
unsigned char PassWord[] = "000000"; 
unsigned char PassW_Set[] = "123456";

定义我们需要的全局变量。

    LCD_Init();
	time_init();
	Start_up();
	Music();
	Delay(1000);
	Delete();

对开机界面进行初始化,接下来就可以进入我们循环体中咯~

Number = Matrixkey();
		if(Number == 13)
		{
			Buzzer(200);
			OK_Flag = 1;
		}
		if(Number == 15)
		{
			Buzzer(200);
			if(Lock_Flag != 0)
			{
				Lock_Flag = 0;
				while(StepGround--)
							{
								Motor_Drive41(0,5);
							}
						MotorStop();
						StepGround = 100;
			}	
		}
		if(Number == 16) 
		{
			Buzzer(200);
			Delete();
			Page_Flag++;	
			if((Lock_Flag == 1) && (Page_Flag == 1))
			{
				Page_Flag = 2;
			}
			if(Page_Flag == 3)Page_Flag = 0;
		}

第一步要对我们各个按键的功能逐一实现,在实现过程中我们可以借助不同的标志位来实现我们想要实现的功能

if(Page_Flag == 0) //显示主页面万年历
		{
			LCD_Display_Main(Lock_Flag);
		}
		if(Page_Flag == 1)	//密码输入显示
		{
			LCD_ShowString(1,1,"PassWord:");
			if(Number == 14)//删除操作
			{
					Buzzer(200);
					LCD_ShowString(2,count,"                ");
					count--;
				}
			if( (Number >= 1) && (Number <= 9) && (count < 6))
			{
				Buzzer(200);
				PassWord[count] = Number + 0x30;
				LCD_ShowChar(2,count + 1,PassWord[count]);
				Delay(500);
				LCD_ShowChar(2,count + 1,'*');
				count++;
				if(count == 6)
				{
					if(OK_Flag == 1)
					{
					count = 0;
					OK_Flag = 0;					
					if(strcmp(PassWord,PassW_Set)==0)//密码比对
					{
						while(StepGround--)
							{
								Motor_Drive41(1,5);
							}
							MotorStop();
							StepGround = 100;
							Delete();
							LCD_ShowString(1,1,"PassWord:");
							LCD_ShowString(2,1,"Success");
							Delay(2000);
							Page_Flag = 0;
							Lock_Flag = 1;
							Delete();
					}
					else
					{
						Delete();
						LCD_ShowString(1,1,"PassWord:");
						LCD_ShowString(2,1,"Fail");
						Error_Num++;
						Delay(1000);
						Delete();
						Page_Flag = 0;
					}
				}				
			}
		}
	}
		if((Page_Flag == 2) && (Lock_Flag == 0))Page_Flag = 0;//关锁不能更改密码
		if((Page_Flag == 2) && (Lock_Flag == 1))//开锁更改密码
		{
			LCD_ShowString(1,1,"NewPassWord:");
			if(Number == 14)//删除操作
			{
					Buzzer(200);
					LCD_ShowString(2,count,"                ");
					count--;
				}
			if( (Number >= 1) && (Number <= 9) && (count < 6))//密码更改
			{
				Buzzer(200);
				PassW_Set[count] = Number + 0x30;
				LCD_ShowChar(2,count + 1,PassW_Set[count]);
				Delay(500);
				LCD_ShowChar(2,count + 1,'*');
				count++;
				if(count == 6)
				{
					if(OK_Flag == 1)
					{
						count = 0;
						OK_Flag = 0;
						Delete();
						LCD_ShowString(1,1,"NewPassWord:");
						LCD_ShowString(2,1,"SetSuccess");
						Delay(1000);
						Delete();
						Page_Flag = 0;
					}		
				}
			}
		}
		if(Error_Num == 3)//密码错误3次提醒
		{
			Error_Num = 0;
			Delete();
			LCD_ShowString(1,3,"PlaseWait 3s");
			Buzzer(6000);
			Delete();
		}

四、总结

可能大家发现介绍里面有开机音乐这一项功能,我们可以通过该变蜂鸣器声调来模拟音乐,如下

void Music()
{
		unsigned char x = 200;
		unsigned int count = 500;
		P3M1 = 0x00;
		P3M0 = 0x00;
		while(1)
		{
			count += 100;
			while(x--)
			{
				buzzer = ~buzzer;
				Delay_M(count);
			}
			x = 200;
			if(count == 1200)break;
		}
		
}

PS:该蜂鸣器为无源蜂鸣器。

最后:此次设计没有设计密码进行掉电不丢失的功能,掉电后密码就会回到设置的初始密码,感兴趣的可以查阅资料怎样将密码存入EEPROM

  1. EEPROM 存储器
    EEPROM 是一种可擦写可编程非易失性存储器件,可以在掉电后保持数据不丢失。单片机的程序可以通过操作 EEPROM 存储器来保持需要保存的数据,如设置参数、校准数据等。当单片机重新上电时,可以通过读取 EEPROM 存储器中的数据来恢复之前的设置。

 最后附上主函数代码文章来源地址https://www.toymoban.com/news/detail-770537.html


#include <STC15F2K60S2.H>
#include "LCD1602.h"
#include "Delay.h"
#include "Matrixkey.h"
#include "stepmotor.h"
#include "PCF8563.h"
#include "Start.h"
#include <string.h>

unsigned char Page_Flag;
unsigned char Lock_Flag;
unsigned char OK_Flag;
unsigned char Error_Num;
unsigned char PassWord[] = "000000"; 
unsigned char PassW_Set[] = "123456";
void main()
{
	unsigned char Number;
	unsigned char count = 0;
	unsigned int StepGround = 100;
	LCD_Init();
	time_init();
	Start_up();
	Music();
	Delay(1000);
	Delete();
	while(1)
	{
		Number = Matrixkey();
		if(Number == 13)
		{
			Buzzer(200);
			OK_Flag = 1;
		}
		if(Number == 15)
		{
			Buzzer(200);
			if(Lock_Flag != 0)
			{
				Lock_Flag = 0;
				while(StepGround--)
							{
								Motor_Drive41(0,5);
							}
						MotorStop();
						StepGround = 100;
			}	
		}
		if(Number == 16) 
		{
			Buzzer(200);
			Delete();
			Page_Flag++;	
			if((Lock_Flag == 1) && (Page_Flag == 1))
			{
				Page_Flag = 2;
			}
			if(Page_Flag == 3)Page_Flag = 0;
		}
		if(Page_Flag == 0) //ʱ¼äÏÔʾ
		{
			LCD_Display_Main(Lock_Flag);
		}
		if(Page_Flag == 1)	
		{
			LCD_ShowString(1,1,"PassWord:");
			if(Number == 14)
			{
					Buzzer(200);
					LCD_ShowString(2,count,"                ");
					count--;
				}
			if( (Number >= 1) && (Number <= 9) && (count < 6))
			{
				Buzzer(200);
				PassWord[count] = Number + 0x30;
				LCD_ShowChar(2,count + 1,PassWord[count]);
				Delay(500);
				LCD_ShowChar(2,count + 1,'*');
				count++;
				if(count == 6)
				{
					if(OK_Flag == 1)
					{
					count = 0;
					OK_Flag = 0;					
					if(strcmp(PassWord,PassW_Set)==0)
					{
						while(StepGround--)
							{
								Motor_Drive41(1,5);
							}
							MotorStop();
							StepGround = 100;
							Delete();
							LCD_ShowString(1,1,"PassWord:");
							LCD_ShowString(2,1,"Success");
							Delay(2000);
							Page_Flag = 0;
							Lock_Flag = 1;
							Delete();
					}
					else
					{
						Delete();
						LCD_ShowString(1,1,"PassWord:");
						LCD_ShowString(2,1,"Fail");
						Error_Num++;
						Delay(1000);
						Delete();
						Page_Flag = 0;
					}
				}				
			}
		}
	}
		if((Page_Flag == 2) && (Lock_Flag == 0))Page_Flag = 0;
		if((Page_Flag == 2) && (Lock_Flag == 1))
		{
			LCD_ShowString(1,1,"NewPassWord:");
			if(Number == 14)
			{
					Buzzer(200);
					LCD_ShowString(2,count,"                ");
					count--;
				}
			if( (Number >= 1) && (Number <= 9) && (count < 6))
			{
				Buzzer(200);
				PassW_Set[count] = Number + 0x30;
				LCD_ShowChar(2,count + 1,PassW_Set[count]);
				Delay(500);
				LCD_ShowChar(2,count + 1,'*');
				count++;
				if(count == 6)
				{
					if(OK_Flag == 1)
					{
						count = 0;
						OK_Flag = 0;
						Delete();
						LCD_ShowString(1,1,"NewPassWord:");
						LCD_ShowString(2,1,"SetSuccess");
						Delay(1000);
						Delete();
						Page_Flag = 0;
					}		
				}
			}
		}
		if(Error_Num == 3)
		{
			Error_Num = 0;
			Delete();
			LCD_ShowString(1,3,"PlaseWait 3s");
			Buzzer(6000);
			Delete();
		}
	}
}

到了这里,关于基于STC15单片机的智能密码锁(矩阵按键输入)设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于单片机的电子密码锁设计

    1.设计任务 利用AT89C51单片机为核心控制元件,设计一个简易的电子密码锁,可设置四位密码,输入错误三次,报警灯亮起(红灯亮起),输入正确,绿灯闪烁三次。可通过LCD显示屏查看密码,并可通过特殊键位清除密码。 本系统由AT89C51单片机系统(主要是AT89C51单片机最小系

    2024年02月02日
    浏览(38)
  • 基于51单片机的电子密码锁

    主要功能: 1、6位密码开锁 可以修改用户密码和管理员密码 断电记忆 3次错误报警锁住键盘

    2024年02月11日
    浏览(40)
  • 基于51单片机的密码锁设计

    电子密码锁设计,以AT89C51为主控,晶振电路和复位电路共同组成最小系统,使得单片机可以正常运行。矩阵按键作为输入模块,输入密码,LCD1602作为显示设备,显示输入的密码和提示语句,AT24C02作为EEPROM存储器,使用LED模拟“锁”,表示锁的开启和关闭状态。系统掉电后,

    2024年02月11日
    浏览(51)
  • 基于51单片机密码锁(修改密码,串口上锁解锁,仿真)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 一、仿真图 二、步骤 1.矩阵按键 2.串口配置 3.串口接收数据判断 4.修改密码+密码输入 总结 前言 LCD1602+矩阵按键+串口上锁解锁+修改密码   提供参考 代码如下: 代码如下(示例): 这里把判断拿

    2024年02月15日
    浏览(35)
  • 基于51单片机的电子密码锁设计

    一.硬件方案         本系统由STC89C52单片机、4*4矩阵键盘,蜂鸣器,复位电路和晶振电路、继电器等组成,4*4键盘主要用于密码的输入和修改,蜂鸣器报警,复位电路和晶振电路与STC89C52单片机组成单片机最小系统。它具有设置、修改6位用户密码、输错报警、密码错误报

    2024年02月16日
    浏览(36)
  • (含代码)基于51单片机电子密码锁设计

    一.硬件说明 采用STC89C51作为主控芯片,结合矩阵按键输入模块、数码管显示模块、LCD1602液晶显示、LED、蜂鸣器报警器等电路模块实现开锁、上锁、报警、密码更改等功能,设计一款可修改密码且具有报警功能的液晶显示电子密码锁。 主要由STM32单片机+最小系统+LCD1602液晶显

    2024年01月16日
    浏览(41)
  • 基于51单片机的红外密码锁设计[proteus仿真]

    密码锁检测系统这个题目算是课程设计和毕业设计中常见的题目了,本期是一个基于51单片机的红外密码锁设计 需要的源文件和程序的小伙伴可以关注公众号【阿目分享嵌入式】,赞赏任意文章 2¥,私信阿目【112基于51单片机的红外密码锁设计】即可获取(看到消息会第一时

    2024年02月21日
    浏览(46)
  • 基于STM32单片机的密码锁(Proteus仿真、程序)

    由STM32F103单片机最小系统+ 4*4矩阵键盘+LCD1602液晶显示+蜂鸣器+继电器模块 1、采用STM32F103为主控芯片 2、通过4*4矩阵键盘实现密码输入、功能键等排列如下 1     2    3     删除 4     5    6     修改密码 7     8    9     重新输入 返回  0   确认   紧急开锁键 3、每按下一次

    2024年02月07日
    浏览(49)
  • 0232-基于单片机的RFID刷卡密码锁电路设计

    1、采用STC89C52单片机作为主控芯片; 2、采用1602液晶显示使用过程及状态(液晶屏亮度可随光线自动调整); 3、采用矩阵键盘输入6位密码,输入密码正确则锁打开,显示open!输入错误次数超过3次,蜂鸣器报警并且锁定键盘; 4、可以自己修改密码,必须是锁打开时才能改密

    2024年02月20日
    浏览(50)
  • 基于51单片机LCD1602的简易矩阵键盘密码锁

    初次开始写博客,表达方面也许会有很多不足,希望自己能通过这种方式巩固自己的学习和锻炼表达能力,同时也是对于自己学习的记录。 四位密码锁,密码可更改,输入仅四次以内有效 矩阵键盘定义为1-16,顺序为从左上到右下,1-10号为密码输入键位,对键码取余,输入

    2024年01月23日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包