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

该文介绍了使用51单片机设计的电子密码锁,具备开锁、上锁、修改密码功能。通过Proteus8.9进行仿真,Keil5编写代码。LCD显示模块用于提示信息,LED灯模拟锁状态,采用89C52为主控芯片。代码中包括LCD显示、矩阵按键扫描的实现,以及开锁和修改密码的详细逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

0 功能介绍

1、实现开锁、上锁、修改密码的功能。

2、初始密码666666,点击开锁后,输入密码,点击确认键,然后灯亮,示意开锁。

3、点击修改密码,需要先输入原密码点击确认后,再输入新密码点击确认,修改成功后显示成功标识。

4、点击上锁按钮上锁。

1 软件平台及代码开源

仿真软件:Proteus 8.9

代码编写:Keil5

百度网盘链接:

链接:https://pan.baidu.com/s/1DhzBwq-PywJVlyiuO_-AOA
提取码:f6kg
–来自百度网盘超级会员V4的分享

Gitee链接:

51单片机项目学习: 这个仓库拿来保存一些51单片机项目学习 (gitee.com)

2 仿真硬件选型

在这里插入图片描述

LM016L显示提示信息,LED灯作为模拟锁,主控是89C52,使用矩阵按键。

在这里插入图片描述

3 代码编写

3.1 整体设计思路

​ 在5ms定时器中进行按键扫描,获得键值,然后在主循环中实现相应键值按下后的相关功能,主要设置3个功能,开锁、上锁、修改密码,相应的按键按下后,就将对应的功能标志位置1,对应的标志位置1后,就会执行相关的功能函数。

3.2 软件代码设计

3.2.1 LCD显示

​ LCD初始化程序使用的是裁剪过的普中的初始化代码,显示功能函数使用的是宋学松老师手把手教你学51单片机中的代码。

/**
  * @name    Lcd1602_Delay1ms
  * @brief   延时函数,延时1ms
  * @param   : [输入/出] 
  * @retval  返回值
  */
void Lcd1602_Delay1ms(unsigned int c)   //误差 0us
{
    unsigned char a,b;
	for (; c>0; c--)
	{
		 for (b=199;b>0;b--)
		 {
		  	for(a=1;a>0;a--);
		 }      
	}
    	
}
/**
  * @name    LcdWriteCom
  * @brief   向LCD写入一个字节的命令
  * @param   com
  * @retval  返回值
  */
void LcdWriteCom(unsigned char com)	  //写入命令
{
	LCD1602_E = 0;     //使能
	LCD1602_RS = 0;	   //选择发送命令
	LCD1602_RW = 0;	   //选择写入
	
	LCD1602_DATAPINS = com;     //放入命令
	Lcd1602_Delay1ms(1);		//等待数据稳定

	LCD1602_E = 1;	          //写入时序
	Lcd1602_Delay1ms(5);	  //保持时间
	LCD1602_E = 0;
}
/**
  * @name    LcdWriteData
  * @brief   向LCD写入一个字节的数据
  * @param   dat
  * @retval  返回值
  */
void LcdWriteData(unsigned char dat)			//写入数据
{
	LCD1602_E = 0;	//使能清零
	LCD1602_RS = 1;	//选择输入数据
	LCD1602_RW = 0;	//选择写入

	LCD1602_DATAPINS = dat; //写入数据
	Lcd1602_Delay1ms(1);

	LCD1602_E = 1;   //写入时序
	Lcd1602_Delay1ms(5);   //保持时间
	LCD1602_E = 0;
}	
/**
  * @name    LcdInit
  * @brief   初始化LCD屏
  * @param   无
  * @retval  返回值
  */
void LcdInit()						  //LCD初始化子程序
{
 	LcdWriteCom(0x38);  //开显示
	LcdWriteCom(0x0c);  //开显示不显示光标
	LcdWriteCom(0x06);  //写一个指针加1
	LcdWriteCom(0x01);  //清屏
	LcdWriteCom(0x80);  //设置数据指针起点
}	
/**
  * @name    LcdSetCursor
  * @brief   设置显示 RAM 起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标
  * @param   x y
  * @retval  返回值
  */
void LcdSetCursor(unsigned char x, unsigned char y)
{
	unsigned char addr;

	if (y == 0) //由输入的屏幕坐标计算显示 RAM 的地址
		addr = 0x00 + x; //第一行字符地址从 0x00 起始
	else
		addr = 0x40 + x; //第二行字符地址从 0x40 起始
	LcdWriteCom(addr | 0x80); //设置 RAM 地址
}
/**
  * @name    LcdShowStr
  * @brief   在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针
  * @param   x y str
  * @retval  返回值
  */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
	LcdSetCursor(x, y); //设置起始地址
	while (*str != '\0') //连续写入字符串数据,直到检测到结束符
	{
		LcdWriteData(*str++); //先取 str 指向的数据,然后 str 自加 1
	}
}
3.2.2 矩阵按键扫描函数

​ 按键扫描函数也是参考的普中的代码,但是他是用的delay延时,但是我是将按键扫描函数放置在5ms的定时器中断服务函数中,所以使用的是计数延时的方法,现在这个函数,按键按下后,会一直保持那个键值,按键抬起后,键值才会清零,如果想实现单次触发,需要在使用的时候,手动将键值清零,便可以实现单次按键了,不清零就实现的长按。

/**
  * @name    KeyScan
  * @brief   按键检测函数
  * @param   : [输入/出] 
  * @retval  返回值
  */
void KeyScan(void)
{
    static u8 count = 0;
	GPIO_KEY=0x0f;
	if(GPIO_KEY!=0x0f && KeyState == 0)
	{
        count ++;
		if(GPIO_KEY!=0x0f && count > 2 && KeyState == 0)
		{
            count = 0;
			KeyState = 1;
			//列
			GPIO_KEY=0X0F;
			switch(GPIO_KEY)
			{
				case(0X07):	KeyValue=1;break;
				case(0X0b):	KeyValue=2;break;
				case(0X0d): KeyValue=3;break;
				case(0X0e):	KeyValue=4;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 if(GPIO_KEY==0x0F && KeyState == 1)
    {
        KeyState = 0;
        KeyValue = 0;
    }
}

实现单次检测的方案,这样写就能够只使用一次按键按下的键值

void KeyDownFunction()
{
    u8 KeyValueTemp = 0;
    if(KeyState == 1)
    {
        KeyValueTemp = KeyValue;//用变量保存按下的键值
        if(KeyValue != 0)//实现单次检测按键
            KeyValue = 0;
        //功能代码 
        
    }
}
3.2.3 按键按下的功能函数

​ 按键按下后,如果是开锁键,那就打开开锁的功能代码块,关锁和修改密码同理。

void KeyDownFunction()
{
    u8 KeyValueTemp = 0;
    if(KeyState == 1)
    {
        KeyValueTemp = KeyValue;
        if(KeyValue != 0)//实现单次检测按键
            KeyValue = 0;
        if(KeyValueTemp == KEY_Open && OpenFlag == 0)//使能开锁功能函数
        {
            OpenFlag   = 1;
        }else if(KeyValueTemp == KEY_Close && CloseFlag == 0)//使能关锁功能函数
        {
            CloseFlag  = 1;
        }else if(KeyValueTemp == KEY_Change && ChangeFlag == 0)//使能修改密码功能函数
        {
            ChangeFlag = 1;
        }
        if(OpenFlag == 1)//开锁功能使能
        {  
            OpenLock(KeyValueTemp);
        }
        if(CloseFlag == 1)//关锁功能使能
        {
            sprintf((char*)DisBuff,"----  lock  ----");
            LcdShowStr(0,1,DisBuff);
            CloseFlag = 0;
            LED = 1;
        }
        if(ChangeFlag == 1)//修改密码功能使能
        {
            ChangePassword(KeyValueTemp);
        }
    }
}
3.2.4 开锁功能

​ 由于想要实现不影响其他代码段的功能,没有使用机器周期延时,或者while等循环输入,这部分就是实现的开锁,详细可以看代码注释。大致思路是,会有一个OpenCount计数器,点击开锁按钮后,计数器值是0,就只是进入输密码的界面,同时将计数值加1,那下一次执行到该函数就会进入修改密码的代码段。

​ 在修改密码的代码段,正常的话就是修改密码,OpenCount加1,就是下一位密码修改,但是如果点击了回退按钮,就会将OpenCount减1,回退到上一个位置,同时将该位密码清空。

​ 如果想要在输入密码的时候显示 * 号,那么只需让DisBuff[OpenCount+5]的值一直是 * 就可以了。

void OpenLock(u8 KeyValueTemp)
{
    static u8 OpenCount = 0;
    static u8 PasswordTemp[7] = {0};
    if(OpenCount == 0)//一个计数器,为0时,就是刚进入开锁状态的时候,显示pwd :字符串
    {
        sprintf((char*)DisBuff,"pwd :           ");
        LcdShowStr(0,1,DisBuff);
        OpenCount++;//显示完后把计数器加一
    }else//下次点击就进入else
    {
        if(KeyValueTemp == KEY_Back && OpenCount > 1)//当点击回退按钮
        {
            OpenCount --;//回到上一个密码数的位置
            DisBuff[OpenCount+5] = ' ';//将显示位清空
            PasswordTemp[OpenCount-1] = 0;//将该位密码置0,因为密码使用的字符串,一般ASCLL不会为0
            LcdShowStr(0,1,DisBuff);
        }else if(OpenCount < 7)//密码设定为6位,所以6位输完后就不进入输密码的功能块了
        {
            /*
                这里有个KeyValueTable是因为按键按下的值不是实际我排版的值,所以用数组做了一次转换
            */
            DisBuff[OpenCount+5] = '0' + KeyValueTable[KeyValueTemp-1];//将显示位显示输入的数值
            PasswordTemp[OpenCount-1] = '0' + KeyValueTable[KeyValueTemp-1];//将输入的数值保存
            LcdShowStr(0,1,DisBuff);
            OpenCount++;//该位处理完后进到下一位
        }
    }
    if(OpenCount > 6 && KeyValueTemp == KEY_Confirm)//6位密码输完,又点击了确认按钮的话,就开始比较密码
    {
        OpenFlag  = 0;
        OpenCount = 0;
        if(strcmp(Password,PasswordTemp)==0)
        {
            sprintf((char*)DisBuff,"----  open  ----");
            LcdShowStr(0,1,DisBuff);
            LED = 0;
        }else
        {
            sprintf((char*)DisBuff,"----  lock  ----");
            LcdShowStr(0,1,DisBuff);
            LED = 1;
        }
    }
}
3.2.5 修改密码功能

​ 这是修改密码,原理大概和开锁功能差不多。就是多了个ChangeMode,该变量为0是输入旧密码,为1是输入新密码。大致的思路差不多。

void ChangePassword(u8 KeyValueTemp)
{
    static u8 ChangeCount = 0;
    static u8 ChangeMode  = 0;//0是输入旧密码,1是输入新密码
    static u8 PasswordTemp[7] = {0};
    static u8 NewPasswordTemp[7] = {0};
    if(ChangeMode == 0)
    {
        if(ChangeCount == 0)//一个计数器,为0时,就是刚进入修改密码状态的时候,显示pwd :字符串
        {
            sprintf((char*)DisBuff,"pwd :           ");
            LcdShowStr(0,1,DisBuff);
            ChangeCount++;//显示完后把计数器加一
        }else//下次点击就进入else
        {
            if(KeyValueTemp == KEY_Back && ChangeCount > 1)//当点击回退按钮
            {
                ChangeCount --;//回到上一个密码数的位置
                DisBuff[ChangeCount+5] = ' ';//将显示位清空
                PasswordTemp[ChangeCount-1] = 0;//将该位密码置0,因为密码使用的字符串,一般ASCLL不会为0
                LcdShowStr(0,1,DisBuff);
            }else if(ChangeCount < 7)//密码设定为6位,所以6位输完后就不进入输密码的功能块了
            {
                /*
                    这里有个KeyValueTable是因为按键按下的值不是实际我排版的值,所以用数组做了一次转换
                */
                DisBuff[ChangeCount+5] = '0' + KeyValueTable[KeyValueTemp-1];//将显示位显示输入的数值
                PasswordTemp[ChangeCount-1] = '0' + KeyValueTable[KeyValueTemp-1];//将输入的数值保存
                LcdShowStr(0,1,DisBuff);
                ChangeCount++;//该位处理完后进到下一位
            }
        }
        if(ChangeCount > 6 && KeyValueTemp == KEY_Confirm)//6位密码输完,又点击了确认按钮的话,就开始比较密码
        {
            ChangeCount = 0;
            if(strcmp(Password,PasswordTemp)==0)//密码正确就可以输入新密码了
            {
                sprintf((char*)DisBuff,"new :           ");
                LcdShowStr(0,1,DisBuff);
                ChangeCount ++;
                ChangeMode = 1;
            }else
            {
                ChangeFlag  = 0;
                sprintf((char*)DisBuff,"----  lock  ----");
                LcdShowStr(0,1,DisBuff);
                LED = 1;
            }
        }
    }else if(ChangeMode == 1)
    {
        if(KeyValueTemp == KEY_Back && ChangeCount > 1)//当点击回退按钮
        {
            ChangeCount --;//回到上一个密码数的位置
            DisBuff[ChangeCount+5] = ' ';//将显示位清空
            NewPasswordTemp[ChangeCount-1] = 0;//将该位密码置0,因为密码使用的字符串,一般ASCLL不会为0
            LcdShowStr(0,1,DisBuff);
        }else if(ChangeCount < 7)//密码设定为6位,所以6位输完后就不进入输密码的功能块了
        {
            /*
                这里有个KeyValueTable是因为按键按下的值不是实际我排版的值,所以用数组做了一次转换
            */
            DisBuff[ChangeCount+5] = '0' + KeyValueTable[KeyValueTemp-1];//将显示位显示输入的数值
            NewPasswordTemp[ChangeCount-1] = '0' + KeyValueTable[KeyValueTemp-1];//将输入的数值保存
            LcdShowStr(0,1,DisBuff);
            ChangeCount++;//该位处理完后进到下一位
        }
        if(ChangeCount > 6 && KeyValueTemp == KEY_Confirm)//6位密码输完,又点击了确认按钮的话,就开始比较密码
        {
            ChangeFlag  = 0;
            ChangeCount = 0;
            sprintf((char*)DisBuff,"---- success----");
            LcdShowStr(0,1,DisBuff);
            ChangeMode = 0;
            strcpy(Password,NewPasswordTemp);
        }
    }
}

4 总结

​ 这个设计功能比较简单,也有些地方功能不全,后面更新,欢迎交流。

单片机原理与应用 课程设计报告 题 目 基于51单片机电子密码锁设计 系 别 物理与电子工程学院 专 业 电子信息科学与技术 学生姓名 学 号 班 级 2013年 12月26日 摘要 电子密码锁是一种通过密码输入来控制电路或是芯片工作,从而控制机械开关地闭合 ,完成开锁、闭锁任务地电子产品.在保密性、操作地方便性、密码地可变性、和一些自 动化地功能上已经远远超过了机械密码锁.因此其应用非常广泛.而且由于其使用微型计 算机地特质,导致其可以灵活地挂载电子化设备,比如界面友好地显示设备,方便快捷 地输入设备等.本文简要介绍了一种基于AT89C51单片机电子密码锁设计,主要采用汇 编程序完成整个软件地设计,可以实现简易地电子密码锁功能. 关键词:4×4矩阵键盘;AT89C51;密码锁;单片机 目录 一、绪论 …………………………………………………………………………………………3 二、系统所要完成地功能………………………………………………………………………3 三、系统总体方案设计 …………………………………………………………………………4 四、硬件电路设计 ………………………………………………………………………………6 4.1单片机最小系统…………………………………………………………………………6 4.2 键盘电路设计……………………………………………………………………………6 4.3 LCD显示电路……………………………………………………………………………8 4.4 开锁电路…………………………………………………………………………………8 五、软件设计 ……………………………………………………………………………………9 六、系统调试……………………………………………………………………………………13 七、心得体会……………………………………………………………………………………13 参考文献…………………………………………………………………………………………14 附 录 …………………………………………………………………………………………15 源程序清单 ………………………………………………………………………………………15 实物图 ……………………………………………………………………………………………23 一、绪论 在日常地生活和工作中, 住宅与部门地安全防范、单位地文件档案、财务报表以及一些个人资料地保存多以加锁 地办法来解决.若使用传统地机械式钥匙开锁,人们常需携带多把钥匙, 使用极不方便, 且钥匙丢失后安全性即大打折扣.随着科学技术地不断发展,人们对日常生活中地安全保 险器件地要求越来越高.为满足人们对锁地使用要求,增加其安全性,用密码代替钥匙地 密码锁应运而生.密码锁具有安全性高、成本低、功耗低、易操作等优点. 在安全技术防范领域,具有防盗报警功能地电子密码锁逐渐代替传统地机械式密码锁 ,克服了机械式密码锁密码量少、安全性能差地缺点,使密码锁无论在技术上还是在性 能上都大大提高一步.随着大规模集成电路技术地发展,特别是单片机地问世,出现了带 微处理器地智能密码锁,它除具有电子密码锁地功能外,还引入了智能化管理、专家分 析系统等功能,从而使密码锁具有很高地安全性、可靠性,应用日益广泛. 随着人们对安全地重视和科技地发展,许多电子智能锁(指纹识别、IC卡辨认)已在 国内外相继面世.但是这些产品地特点是针对特定地指纹和有效卡,只能适用于保密要求 地箱、柜、门等.而且指纹识识别器若在公共场所使用存在容易机械损坏,IC卡还存在容 易丢失、损坏等特点.加上其成本较高,一定程度上限制了这类产品地普及和推广.鉴于 目前地技术水平与市场地接收程度,电子密码锁是这类电子防盗产品地主流. 二、系统所要完成地功能 基于以上思路,本文主要介绍一种使用 STC公司地 STC11F16XE单片机电子密码锁设计,其主要具有如下功能: 1、密码确认功能:密码通过矩阵键盘输入,若密码输入正确,则将通过驱动口发出 高电平信号作为机械制动开锁地依据完成开锁功能.同时在主界面上显示:"The keywords is ok!" 2、密码设置功能:单片机刚刚上电复位后会通过LCD1602界面提示设置密码:"Plea se set the keywords!"而且设置地密码是可重复地,程序运行中可再次通过输入相应密码然后修改 . 3、在密码输入错误时系统会通过LCD1602界面提示密码输入错误字符:"The keywords is false!"同时不做开锁动作. 4、本次设计中利用一只LED代替机械制动系统,灯亮表示开锁,灯灭表示闭锁. 在本次地设计中,具体实现系统设计地过程如下: 1、完成硬件地设计.通过PROTEL99SE绘制单片机最小系统板和矩阵键盘地原理
电子密码锁是一种智能化的锁具,它通过电子技术实现对门的开关控制,可以有效地提高房屋或办公室的安全性。在本篇文章中,我们将介绍如何基于51单片机设计一个简单的电子密码锁设计思路: 电子密码锁设计思路是通过51单片机控制密码输入与门的开关控制。设计需要采用矩阵键盘作为输入设备,将输入的密码与预设密码进行比较,如果相同,则控制门的开关。 硬件设计电子密码锁的硬件设计主要包括以下几个部分: 1. 51单片机控制模块:选择STC89C52RC单片机作为控制模块,具有较强的处理能力和稳定性。 2. 矩阵键盘输入模块:选择4x4的矩阵键盘,通过51单片机的IO口读取用户输入的密码。 3. 驱动电路模块:选择继电器作为驱动装置,通过继电器控制门的开关。 4. 电源模块:选择12V电源,通过稳压电路提供5V电压给单片机和其他电路元件。 软件设计电子密码锁的软件设计主要包括以下几个部分: 1. IO口初始化:设置51单片机的IO口为输入或输出状态。 2. 矩阵键盘扫描:通过循环扫描矩阵键盘,读取用户输入的密码。 3. 密码比较:将用户输入的密码与预设密码进行比较,如果相同,则控制门的开关。 4. 继电器控制:通过控制继电器开关实现门的开关。 总结: 本文介绍了基于51单片机设计电子密码锁的方法。通过矩阵键盘输入密码,将输入的密码与预设密码进行比较,实现对门的开关控制。该电子密码锁具有较高的安全性和可靠性,可应用于家庭、办公室等多种场所。
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年、潜行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值