基于Proteus仿真的51单片机电子密码锁

1.实现功能

  • 矩阵键盘检测
  • 设定六位密码,初试密码为123456
  • 更改密码
  • LCD1602显示
  • 密码删除退格
  • 中断实现蜂鸣器
  • LED灯闪烁

功能非常简陋,制作时间很赶,所以质量一般。



2.逻辑流程图

在这里插入图片描述



3. Proteus原理图仿真

在这里插入图片描述

4.代码实现

矩阵键盘

#include <REGX52.H>
#include "Delay1ms.h"
#define key P1


/**
 * @brief 先行扫描,再列扫描
 */
unsigned char MatrixKey(){
	unsigned char keyValue[16] = {1,2,3,'A',
								  4,5,6,'B',
								  7,8,9,'C',
								'*',0,'#','D'};
    unsigned char num = 100;
    key = 0xF0;
    if(key != 0xF0){
        Delay1ms(10);   //延时抖消
        if(key != 0xF0){    //check again
			key = 0xF0;
            switch(key)   //先确定行
             {
                case 0x70: num=1;  break;   //第一行
                case 0xb0: num=5;  break;   //第二行
                case 0xd0: num=9;  break;   //第三行
                case 0xe0: num=13; break;   //第四行
             }
             key = 0x0F;     //对应IO口拉高,以便检测
             switch(key)   //再确定列
             {
                case 0x07: num=num+0;while(key != 0x0F){}; break;   //第一列
                case 0x0b: num=num+1;while(key != 0x0F){}; break;   //第二列
                case 0x0d: num=num+2;while(key != 0x0F){}; break;   //第三列
                case 0x0e: num=num+3;while(key != 0x0F){}; break;   //第四列
             }
        }
    }
    
	if(num == 100)
		return 100;
	else
		return keyValue[num-1];
}

矩阵键盘的检测行列检测实现功能不赘述,相信各位大佬已经讲得很清楚明白了。

值得注意的是,检测键盘时要松手后再返回键值,所以最后列检测时加一个while循环,当未松手时就进入死循环不返回。

LCD部分

#include <REGX52.H>

//引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}


  
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}


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


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


主函数检测密码部分

void main(){	
	Timer0Init();
	LCD_Init();
	led = 0;	
	
    while(1){
        getkeyNum = MatrixKey();
		
		//如果有按键输入
        if(getkeyNum != 100){
			
			//输入密码成功后修改密码
			if(open == 't'){
				resetPW(getkeyNum);
				open = 'f';
				continue;
			}
			
			//如果按下删除键'B'
			if(getkeyNum == 'B'){
				i--;
				LCD_ShowChar(1,i,' ');
				continue;
			}
			
		
			if(i<=6){
				//输出按键值
				if(getkeyNum < 10 )
					LCD_ShowChar(1,i,getkeyNum+48);
				else
					LCD_ShowChar(1,i,getkeyNum);
				
				pw[i-1] = getkeyNum;		//存入按键值
				i++;
			}else{
			
				if(getkeyNum == 'D'){		//如果密码相等,显示开锁成功
					if(pw[0]==passWord[0]&& pw[1]==passWord[1]&& pw[2]==passWord[2]&& pw[3]==passWord[3]&& pw[4]==passWord[4] && pw[5]==passWord[5]){
						LCD_ShowString(2,1,"OPEN!");
						led = 1;			//点亮LED
						open = 't';	
						startBeep();		//打开蜂鸣器
						Delay999ms();
						stopBeep();			//关闭蜂鸣器
						led = 0;
						LCD_ShowString(2,1,"      "); 
						
					}
					//如果密码不符合,清空输入密码的显示屏
					else{
						LCD_ShowString(2,1,"Failed!");
						Delay999ms();
						LCD_ShowString(2,1,"       ");
					}
					//重置pw,重置输入密码显示位置
					LCD_ShowString(1,1,"      ");
					i=1;	
				}
			}
		}	
	}
}

修改密码部分

//重置密码
void resetPW(unsigned char getkeyNum){
	if(getkeyNum == 'A'){
		LCD_ShowString(2,1,"RESET");
		LCD_ShowString(1,1,"      ");		
		i=1;		//重置显示位置
		m=0;
		while(1){
			
			//输入六次,若已经输入完成,显示SUCCESS
			if(m>=6){
				LCD_ShowString(2,1,"SUCCESS");
				Delay999ms();
				LCD_ShowString(2,1,"       ");
				LCD_ShowString(1,1,"       ");
				i=1;
				break;
			}
			resetNum = MatrixKey();
			//如果有按键输入
			if(resetNum != 100){
				//如果按下删除键'B'
				if(resetNum == 'B'){
					m--;
					LCD_ShowChar(1,m+1,' ');
					continue;
				}
					
				//输出按键值
				if(resetNum < 10 )
					LCD_ShowChar(1,m+1,resetNum+48);
				else
					LCD_ShowChar(1,m+1,resetNum);
			
				passWord[m] = resetNum; m++;	//修改密码
			}
		}
	}
}

修改密码部分有瑕疵,且代码冗余比较高。


中断实现蜂鸣器
void Timer0Init(){
	EA = 0;		   //关闭总中断
	ET0 = 1;	   //允许T0中断
	TMOD = 0x01;	//定时器模式,T0使用工作方式1
	TH0 = 0x18;    //该初值使隔段时间产生一次中断
	TL0 = 0xFC;
	TR0 = 1;		//打开T0定时器
} 

//打开蜂鸣器
void startBeep(){
	EA = 1;
}
//关闭蜂鸣器
void stopBeep(){
	EA = 0;
}

void Timer0() interrupt 1  {
	TH0 = 63628/256;    	//通过定时器控制蜂鸣器发声频率
	TL0 = 63628%256;
	beep=~beep;				//反复切换高低电平。 
}

定时器随便找的一个可以发声的频率。通过中断总开关EA控制蜂鸣器的打开与否,若使用多个中断,此方法不可用。


所有代码:

https://gitee.com/ClarenceXH/51MCU-electronic-coded-lock



5.效果展示

在这里插入图片描述

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


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


更改密码:

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

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

西叶胡杨

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

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

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

打赏作者

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

抵扣说明:

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

余额充值