电子密码锁设计

01
设计要求
(1)密码为6位长度,初始值是111111。有三次登陆机会,每错一次,红灯及蜂鸣器各亮、响一秒,液晶显示错误信息。错三次后,禁止再登陆。正确登陆后绿灯亮。
(2)可修改密码,但须先正确输入原密码。设置新密码需连续正确输入两次,同时密码须有相应格式,如密码需8位数字。(其余格式,如不能连续8位相同数字、符号*#可作为密码等可根据情况自行设置)。
(3)输入密码时可用*显示已输入密码,用-表示未输入的部分。可设删除按键,可以删除所输入的数字;有取消按键,可以取消修改密码,取消登陆等功能。

02
程序

#include<reg52.h>
#include<intrins.h>
#include "stdio.h"
#include "string.h"
#define uchar unsigned char
#define uint unsigned int
    
// 定义LCD引脚
sbit LCM_RW=P2^5; 
sbit LCM_RS=P2^6;
sbit LCM_E=P2^7;
#define LCM_Data P0

// 用于检测LCM状态字中的Busy标识
#define Busy 0x80 

// 按键定义
sbit K1=P1^0;    
sbit K2=P1^1;
sbit K3=P1^2;
sbit K4=P1^3;
sbit K5=P1^4;
sbit K6=P1^5;
sbit K7=P1^6;
sbit K8=P1^7;

sbit red=P2^0;
sbit green=P2^1;
sbit beep=P2^2;


void LCMInit(void);
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData);
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData);
void WriteDataLCM(unsigned char WDLCM);
void WriteCommandLCM(unsigned char WCLCM,BuysC);
unsigned char ReadDataLCM(void);
unsigned char ReadStatusLCM(void);
void Delay5Ms(void);
void keyscan();
void xianshi();
void keyscan1();
void xianshi1();
void T0_init();
uchar jiance_geshi(uchar *a);

unsigned char code shuru[] ={"shuru:"};
unsigned char code right[] =  {"right"};
unsigned char code error[] =  {"error"};

unsigned char code fail[] =  {" fail "};
unsigned char code kongbai[] ={"               "};
unsigned char code g1[] =  "------";
uchar mima_chushi[6]="111111";
uchar mima[6]="";
uchar mima_xiu[6]="";

// 变量的定义
uchar mima_num;
uchar flag_num,flag_correct,flag_xiugai,flag_error,flag_xiu1,flag_xiu2,flag_quxiao;

// 5ms延时
void Delay5Ms(void)
{
    unsigned int TempCyc = 5552;
    while(TempCyc--);
}

void delay(unsigned int i)
{
    unsigned int j;
    unsigned char k;
    for(j=i;j>0;j--)
        for(k=125;k>0;k--);
}

// 写数据
void WriteDataLCM(unsigned char WDLCM) 
{
	// 检测忙
    ReadStatusLCM(); 
    LCM_Data = WDLCM;
    LCM_RS = 1;
    LCM_RW = 0;
	// 若晶振速度太高可以在这后加小的延时
    LCM_E = 0; 
	// 延时
    LCM_E = 0; 
    LCM_E = 1;
}

// 写指令
// BuysC为0时忽略忙检测
void WriteCommandLCM(unsigned char WCLCM, BuysC) 
{
	// 根据需要检测忙
    if (BuysC) ReadStatusLCM(); 
    LCM_Data = WCLCM;
    LCM_RS = 0;
    LCM_RW = 0;    
    LCM_E = 0;
    LCM_E = 0;
    LCM_E = 1;    
}

// 读数据
unsigned char ReadDataLCM(void)
{
    LCM_RS = 1; 
    LCM_RW = 1;
    LCM_E = 0;
    LCM_E = 0;
    LCM_E = 1;
    return(LCM_Data);
}

// 读状态
unsigned char ReadStatusLCM(void)
{
    LCM_Data = 0xFF; 
    LCM_RS = 0;
    LCM_RW = 1;
    LCM_E = 0;
    LCM_E = 0;
    LCM_E = 1;
	// 检测忙信号
    while (LCM_Data & Busy); 
    return(LCM_Data);
}

// LCM初始化
void LCMInit(void) 
{
    LCM_Data = 0;
	// 三次显示模式设置,不检测忙信号
    WriteCommandLCM(0x38,0); 
    Delay5Ms(); 
    WriteCommandLCM(0x38,0);
    Delay5Ms(); 
    WriteCommandLCM(0x38,0);
    Delay5Ms(); 

    WriteCommandLCM(0x38,1); // 显示模式设置,开始要求每次检测忙信号
    WriteCommandLCM(0x08,1); // 关闭显示
    WriteCommandLCM(0x01,1); // 显示清屏
    WriteCommandLCM(0x06,1); // 显示光标移动设置
    WriteCommandLCM(0x0C,1); // 显示开及光标设置
}

// 按指定位置显示一个字符
void DisplayOneChar(unsigned char X, unsigned char Y, unsigned char DData) //Y 为1 则是第二行
{
    Y &= 0x1;
    X &= 0xF;              // 限制X不能大于15,Y不能大于1
    if (Y) X |= 0x40;      // 当要显示第二行时地址码+0x40;
    X |= 0x80;             // 算出指令码
    WriteCommandLCM(X, 1); //发命令字
    WriteDataLCM(DData);   //发数据
}

// 按指定位置显示一串字符
void DisplayListChar(unsigned char X, unsigned char Y, unsigned char code *DData)
{
    unsigned char ListLength;

  	ListLength = 0;
    Y &= 0x1;
    X &= 0xF; 
	// 限制X不能大于15,Y不能大于1
	//若到达字串尾则退出
    while (DData[ListLength]>0x19)
        {
			// X坐标应小于0xF
            if (X <= 0xF) 
                {
					// 显示单个字符
                    DisplayOneChar(X, Y, DData[ListLength]); 
                    ListLength++;
                    X++;
                }
        }
}

void qing_shuzu(uchar *a)
{
    uchar i,length;
    length=strlen(a);
    for(i=0;i<length;i++)
        a[i]=0;
}

/*中断服务特殊功能寄存器配置*/    
void T0_init()
{
    
    TMOD = 0x01;  //定时器16为计数工作模式
    TH0 =0x4b;
    TL0 =0xfd; //50ms
    ET0 = 1; //开定时器0中断
    TR0 = 0;//启动定时器0
    EA = 1;    //开总中断
}

void keyscan()
{
    if(K1==0)
    {
        delay(10);//延时10ms消除按键抖动
        if(K1==0)
        {
            while(!K1);//若k1键确实按下,则等待k1释放
            mima[mima_num]='1';
            mima_num++;
            delay(5);
            
        }
    }
    if(K2==0)
    {
        delay(10);//延时10ms消除按键抖动 
        if(K2==0)
        {
            while(!K2);//若k2键确实按下,则等待k2释放
            mima[mima_num]='2';
            mima_num++;
            delay(5);
        }    
    }
        if(K3==0)
    {
        delay(10);//延时10ms消除按键抖动
        if(K3==0)
        {
            while(!K3);//若k3键确实按下,则等待k3释放
            mima[mima_num]='3';
            mima_num++;
            delay(5);
        }
    }
        if(K4==0)
    {
        delay(10);//延时10ms消除按键抖动
        if(K4==0)
        {
            while(!K4);//若k4键确实按下,则等待k4释放
            mima[mima_num]='4';
            mima_num++;
            delay(5);    
        }
    }
    
        if(K5==0)  //删除键
    {
        delay(10);  //软件消抖
        if(K5==0)
        {
            mima_num--;
            while(!K5); //松手检测
        }
    }
}    
void xianshi()
{    
    uchar i;
    for(i=0;i<mima_num;i++)
    {
        DisplayOneChar(i+6,0,'*');
    }
    for(i=mima_num;i<6;i++)
    {
        DisplayOneChar(i+6,0,'-');
    }
}
    
/********************功能键扫描 显示*******************************/

void keyscan1()
{
        if(K8==0)  //取消登陆 键
    {
        delay(5);  //软件消抖
        if(K8==0)
        {
            flag_correct=0;  //跳出登陆  
            while(!K8); //松手检测
        }
    }
    
        if(K6==0)   //修改密码
    {
        delay(5);  //软件消抖
        if(K6==0)
        {
            DisplayListChar(0, 1, " first :");     
            DisplayListChar(9, 1, g1);  //显示----
            flag_xiugai=1;
            while(!K6); //松手检测
        }
    }
    
        if(K7==0)   //取消 修改密码
    {
        delay(5);  //软件消抖
        if(K7==0)
        {
            flag_xiugai=0;
            mima_num=0;
            flag_quxiao=1;
            while(!K7); //松手检测
        }
    }    
}

void xianshi1()
{
    uchar i;
    for(i=0;i<mima_num;i++)
    {
        DisplayOneChar(i+9,1,'*');
    }
    for(i=mima_num;i<6;i++)
    {
        DisplayOneChar(i+9,1,'-');
    }
}

void luoji_xianshi()
{
    //static uchar fa=0;
    if(mima_num==0 && flag_num!=3 )  
    {
        DisplayListChar(6, 0, g1);  //显示----
        //fa=1;
    }
    /*if(mima_num==1 && flag_num!=3)  
    {
        DisplayListChar(0, 1, kongbai); //清掉错误信息
    }*/
    if(flag_num==3)
    {
        DisplayListChar(0, 1, fail);   //禁止登陆
        while(1);     //程序卡死
    }
}

uchar jiance_geshi(uchar *a)   //0 表示检查 不通过
{
    uchar i,length,flag;
    flag=0;
    length=strlen(a);
    for(i=1;i<length;i++)
        {if(*(a+i)==(*a))
            flag++;
        }
    if(flag>4)
    {
        return 0;
    }
    else return 1;
    
}
void main()
{
    mima_num=0;
    flag_xiu2=0;
    beep=0;
    T0_init();
    LCMInit();
    DisplayListChar(0, 0, shuru);
    DisplayListChar(6, 0, g1);
    while(1)
    {
        if(flag_xiu2==1)  //
        {
            WriteCommandLCM(0x01,1); //显示清屏
            DisplayListChar(0, 0, shuru);
            DisplayListChar(6, 0, g1);
            flag_xiu2=0;
        }
        keyscan();
        xianshi();
        if(mima_num==6)  //6位输完 开始检测
        {
            if(strcmp(mima,mima_chushi)==1)       //strcmp 
            {
                DisplayListChar(0, 1, error);//错误   strcmp为1 因为mima_chushi 在code区
                red=0;
                beep=1;
                flag_num++;   //错误次数
                mima_num=0;
                TR0=1;
            }        
            else 
            {
                green=0;
                TR0=1;    //开启定时器
                mima_num=0;
                flag_correct=1;
            } 
        }
        luoji_xianshi();
        if(flag_correct) 
        {WriteCommandLCM(0x01,1); //显示清屏
            DisplayListChar(0, 0, right);}
        else DisplayListChar(0, 0, shuru);
        while(flag_correct)  //进入登陆装填
        {
            if(flag_xiu2==0){
            keyscan1();
                if(flag_quxiao) //修改密码取消按键
                {
                    DisplayListChar(0,1,kongbai);
                    flag_quxiao=0;
                }
            if(flag_xiugai==1)
            {
                keyscan();
                xianshi1();
                if(mima_num==6)
                {
                    if(!jiance_geshi(mima))  //检测密码是否符合格式 1表示符合
                    {
                        DisplayListChar(9, 0, error);  //0 不符合 才显示错误
                        flag_xiugai=0;
                        qing_shuzu();
                    }
                    else 
                    {
                        DisplayListChar(0, 1, " second:" );
                        strcpy(mima_xiu,mima);  //符合进入下一步
                        flag_xiu1=1;
                        mima_num=0; //为下一次保存密码准备
                        while(flag_xiu1)
                        {
                            keyscan();
                            xianshi1();
                            if(mima_num==6)
                            {
                                if(strcmp(mima,mima_xiu)==0)       //strcmp 比较这两次密码是否一致
                                {
                                    
                                    strcpy(mima_chushi,mima);
                                    flag_xiu1=0;
                                    delay(1000);
                                    mima_num=0;
                                    flag_xiugai=0;
                                    flag_xiu2=1;
                                }
                                else 
                                {
                                    DisplayListChar(6, 0, "mistake    ");
                                    flag_xiu1=0;
                                    mima_num=0;
                                    flag_xiugai=0;
                                }
                            }
                      }
                    }
                }
            }
        }
    }
    }    
}

/*中断服务程序*/
void timer0() interrupt 1
{
    uchar count;
    TH0 =0x4b;
    TL0 =0xfd; //50ms
    count++;
    if (count == 20)  //1S
    {
        count=0;
        red=1;
        beep=0;
        green=1;
        TR0=0;
    }
}

03
具体操作流程、源码、原理图百度网盘链接:
链接:https://pan.baidu.com/s/1hrss6_tFSxNTgNKiGJiclg
提取码:xxzk

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值