基于51单片机编写的六位电子密码锁由LCD1602显示

基于51单片机编写的六位电子密码锁由LCD1602显示

全部内容由本人原创!
从制定计划到焊接调试完成耗时5天!
此程序仅表示完成该项目其中的一个方法,对有兴趣修改,完善的同学表示欢迎!
*注:每个关键的地方都有注释方便理解哈

原理图如下:

基于51单片机编写的六位电子密码锁由LCD1602显示_第1张图片
主程序main:

#include"reg52.h"
#include"key.h"
#include"lcd.h"
#include “beep.h”

char InputPassword=0;
char PassWordNum=9;
char KeyNum=0; //字符0—9的ASCII码是0x30-0x39 。//任何时候输入的按键值
char PassWordBackup[6]; //原密码
char PassWordBackup2[6]; //临时输入密码
//char Errortimes=3; //定义密码输入错误次数

void Password()
{
char i;
if(KeyChange==1)
{
KeyChange=0; //恢复按键判断状态,让密码只变化一次
PassWordBackup[PassWordNum-9]=KeyNum; //将当前按键的值进行备份
KeyNum=KeyNum%10+0x30; //***此步很重要***将变量转换成字符输出,因为液晶只能显示字符
//0x30-0x39是0-9的ASCLL码字符
LcdShowStr(PassWordNum,1,&KeyNum); //显示相应位
for(i=PassWordNum+1;i<16;i++) //作用是将剩余位清零不显示,避免乱码 “清屏”
{
LcdShowStr(i,1," ");
}

	PassWordNum++;  //索引下一位显示输出
	if(PassWordNum>15)
	{
		PassWordNum=9; //变量恢复初始值,方便下次输入
		KeyChange=1; //为下次按键按下作准备,防止确认界面被频繁刷新
		InputPassword=1; //如果输入的密码达到六位,跳转是否确认密码界面
	}
}

}

void Determine_password() //判断密码函数
{
if(KeyChange1)
{
KeyChange=0;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“Press 1 OK”);
LcdShowStr(0,1,“Press 2 Cancel”);
if(KeyNum
1)
{
InputPassword=2; //跳转进入密码设置成功界面
KeyChange=1;
}
else if(KeyNum==2)
{
LcdShowStr(0,0,“Please Set Init”);
LcdShowStr(0,1,"Password: ");
InputPassword=0;
}
}
}

void Password_Set_successfully() //密码设置成功显示跳转界面
{
static long i=0;
if(KeyChange1)
{
KeyChange=0;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“Password”);
LcdShowStr(0,1,“Set Successfully”);
}
i++;
if(i%500
0) //显示一段时间后准备返回密码输入界面
{
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(7,1,“return 3s”);
}
if(i%10000) //显示一段时间后准备返回密码输入界面
{
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(7,1,“return 2s”);
}
if(i%1500
0) //显示一段时间后准备返回密码输入界面
{
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(7,1,“return 1s”);
}
if(i%2000==0)
{
i=0;
InputPassword=5; //倒计时结束,进入密码输入界面
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“Please Input”);
LcdShowStr(0,1,"Password: ");
}
}

void Password2() //正式输入密码函数
{
static char Errortimes=3; //尽量设计为局部变量,否则程序易跑飞
char i;
char n; //定义一个错误次数的备份变量
if(KeyChange)
{
KeyChange=0;
PassWordBackup2[PassWordNum-9]=KeyNum; //将当前按键的值进行备份
KeyNum=KeyNum%10+0x30;
LcdShowStr(PassWordNum,1,&KeyNum);
for(i=PassWordNum+1;i<16;i++) //作用是将剩余位清零不显示,避免乱码 “清屏”
{
LcdShowStr(i,1," “);
}
PassWordNum++;
if(PassWordNum>15) //密码输入完成,进行对比
{
PassWordNum=9;
for(i=0;i<6;i++)
{
if(PassWordBackup2[i]==PassWordBackup[i])InputPassword=6;//如果循环对比后每次都相等则进入正确界面
else
{
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,” Waring !");
LcdShowStr(0,1,"The last ");

				n=Errortimes;   //将错误次数给变量不改变本身
				n=n%10+0x30;		
				LcdShowStr(9,1,&n);
				LcdShowStr(11,1,"times");
				Errortimes--;
				if(Errortimes<0)
				{
					InputPassword=8;KeyChange=1;break;
				}
				InputPassword=7;break ;  //否则跳出当前循环; //进入警告界面
			}
		}
		KeyChange=1;  //为下次界面只执行一次做准备
	}
}

}

void Change_password() //密码对比成功进入改密选项界面
{
if(KeyChange)
{
KeyChange=0;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“1 ChangePassword”);
LcdShowStr(0,1,“2 Quit”);
}
if(KeyNum1) //回到初始设置密码状态
{
InputPassword=0;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“Please Set Init”);
LcdShowStr(0,1,“Password:”);
}
if(KeyNum
2) //退出选项,并且为下次输入密码做准备
{
InputPassword=5;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,0,“Please Input”);
LcdShowStr(0,1,"Password: ");
}
}

void Waring()
{
static unsigned int i=0;
i++;
if(i%2==0)Beep=!Beep; //针对无源蜂鸣器调频

if(i>60000)
{
	i=0;
	InputPassword=5;
	LcdAreaClear(0,0,16);  //清屏函数,设置起始位和清屏长度
	LcdAreaClear(0,1,16);
	LcdShowStr(0,0,"Please Input");
	LcdShowStr(0,1,"Password:       ");
	KeyChange=0;  //防止输入位错误	
}

}

void Locked()
{
if(KeyChange)
{
KeyChange=0;
LcdAreaClear(0,0,16); //清屏函数,设置起始位和清屏长度
LcdAreaClear(0,1,16);
LcdShowStr(0,1,“Has been locked!”);
}

}

void main()
{
char j;
InitLcd1602();
LcdShowStr(0,0,“Please Set Init”);
LcdShowStr(0,1,“Password:”);
Beep=1;
while(1)
{
if(j%10==0)Beep=!Beep;
switch(InputPassword)
{
case 0 :KeyNum=kscan();Password();break; //跳转初始密码输入
case 1 :KeyNum=kscan();Determine_password();break; //判断界面
case 2 :Password_Set_successfully();break; //密码设置成功界面

		case 5 :KeyNum=kscan();Password2();break;  //正式输入密码界面
		case 6 :KeyNum=kscan();Change_password();break;
		case 7 :Waring();break;  //密码错误警告界面
		case 8 :Locked();break;  //已被锁定界面
		default :break;
	}
}

}

LCD1602程序部分:

#ifndef _lcd_h
#include"reg52.h"

#define LCD1602_DB P0

sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;

/* 等待液晶准备好 */
void LcdWaitReady()
{
unsigned char sta;

LCD1602_DB = 0xFF;
LCD1602_RS = 0;
LCD1602_RW = 1;
do {
    LCD1602_E = 1;
    sta = LCD1602_DB; //读取状态字
    LCD1602_E = 0;
} while (sta & 0x80); //bit7等于1表示液晶正忙,重复检测直到其等于0为止

}
/* 向LCD1602液晶写入一字节命令,cmd-待写入命令值 /
void LcdWriteCmd(unsigned char cmd)
{
LcdWaitReady();
LCD1602_RS = 0;
LCD1602_RW = 0;
LCD1602_DB = cmd;
LCD1602_E = 1;
LCD1602_E = 0;
}
/
向LCD1602液晶写入一字节数据,dat-待写入数据值 /
void LcdWriteDat(unsigned char dat)
{
LcdWaitReady();
LCD1602_RS = 1;
LCD1602_RW = 0;
LCD1602_DB = dat;
LCD1602_E = 1;
LCD1602_E = 0;
}
/
设置显示RAM起始地址,亦即光标位置,(x,y)-对应屏幕上的字符坐标 */
void LcdSetCursor(unsigned char x, unsigned char y)
{
unsigned char addr;

if (y == 0)  //由输入的屏幕坐标计算显示RAM的地址
    addr = 0x00 + x;  //第一行字符地址从0x00起始
else
    addr = 0x40 + x;  //第二行字符地址从0x40起始
LcdWriteCmd(addr | 0x80);  //设置RAM地址

}
/* 在液晶上显示字符串,(x,y)-对应屏幕上的起始坐标,str-字符串指针 */
void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str)
{
LcdSetCursor(x, y); //设置起始地址
while (*str != ‘\0’) //连续写入字符串数据,直到检测到结束符
{
LcdWriteDat(*str++);
}
}

/* 区域清除,清除从(x,y)坐标起始的len个字符位 /
void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len)
{
LcdSetCursor(x, y); //设置起始地址
while (len–) //连续写入空格
{
LcdWriteDat(’ ');
}
}
/
初始化1602液晶 /
void InitLcd1602()
{
LcdWriteCmd(0x38); //16
2显示,5*7点阵,8位数据接口
LcdWriteCmd(0x0C); //显示器开,光标关闭
LcdWriteCmd(0x06); //文字不动,地址自动+1
LcdWriteCmd(0x01); //清屏
}

#endif

按键部分:

//网站http://proteus.5d6d.com
#ifndef _key_h
#define _key_h
#include"reg52.h"

bit KeyChange=0;

char ksta[4][4]={ //所有按键初始值
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
};

char kbackup[4][4]={ //所有按键备份值
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
{1,1,1,1},
};

char code truetable[]={ //真值表
0xC0,0xF9,0xA4,0xB0,
0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,
0xC6,0xA1,0x86,0x8E
};

void delay(unsigned int i) //延时函数
{
while(i–);
}

char kscan()
{
char cnt=0; //定义变量
char j,k; //定义行列扫描变量
P1=0xFF; //按键端口赋初值
for(j=0;j<4;j++) //行扫描
{
P1&=~(0x01< for(k=0;k<4;k++) //列扫描
{
ksta[j][k]=P1&(0x10< if(ksta[j][k]!=kbackup[j][k]) //判断按键初值和备份值是否发生变化
{
delay(100); //延时消抖
if(ksta[j][k]==0) //二次确定该按键按下
{
cnt=j*4+k; //改变变量
KeyChange=1; //使主函数内的按键值判断发生变化让密码输入时只执行一次
}
kbackup[j][k]=ksta[j][k]; //备份按键状态,使程序只执行一次

			}
		}
		
		P1|=0xFF;        //端口置1
	}
return cnt;

}

#endif

蜂鸣器部分:

#ifndef _beep_H
#define _beep_H

#include"reg52.h"

sbit Beep=P3^7;

#endif

了解整体结构不难的哈,并且有很强的拓展性。

你可能感兴趣的:(基于51单片机编写的六位电子密码锁由LCD1602显示)