基于51单片机的6位密码锁设计(数码管和LED矩阵显示)

  本文章是基于51单片机的简易密码锁,无掉电保护,所以没有用到I^C总线协议,仅用到数码管显示,矩阵键盘扫描,led显示。 

 本例程主要实现功能为:定义一个六位数的初始密码,用矩阵输入,输入正确后led被点亮,错误不点亮;摁下任意一个按键蜂鸣器发出声音,松下按键蜂鸣器关闭;按下更改按键可以改密码,改密码时数码管实时显示。按下重试键可以重新输入密码,按下关闭键所有数据清零。

  使用步骤,打开电源,输入6位数初始密码,输入正确锁打开,led亮起;输入正确后,按下更改键后,可以更改密码,改密码时数码管会显示所要更改的密码,更改完成过后按下ok键,新密码被记住,按下close键,重新输入新密码,输入正确后会开锁并且可以重新更改密码。

(参考自清翔51单片机)

 

 

下面来看一下程序,在程序里有相应的注释

#include<reg52.h>                       //定义头文件
#define uchar unsigned char             //定义两个数据类型
#define uint unsigned int         

uchar old1=0,old2=1,old3=2,old4=3,old5=4,old6=5;    //原始密码,可以任意设置0~9
uchar new1,new2,new3,new4,new5,new6;     //定义new,是每次按键按下的数值
uchar a=16,b=16,c=16,d=16,e=16,f=16;     //送入数码管显示的变量
uchar wei,key,temp;                      //定义三个变量,在后面引用

bit allow,genggai,ok,wanbi,retry,close;	 //定义六个非零即一的状态位

sbit dula=P2^6;                         //定义段选端口
sbit wela=P2^7;                         //定义位选端口
sbit beep=P2^3;                         //定义蜂鸣器端口

unsigned char code table[]=                     //声明段选数据
{0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,
0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0x00,0x40};

void delay(unsigned char i)               //定义延时函数,以便后面直接引用
{
	uchar j,k;
  for(j=i;j>0;j--)
    for(k=125;k>0;k--);
}

void display(uchar a,uchar b,uchar c,uchar d,uchar e,uchar f)     //数码管显示函数,对数码管进行赋值
{
   dula=0;
   P0=table[a];
   dula=1;
   dula=0;
   
   wela=0;
   P0=0xfe;
   wela=1;
   wela=0;
   delay(5);
   
   P0=table[b];
   dula=1;
   dula=0;
   
   P0=0xfd;
   wela=1;
   wela=0;
   delay(5);

   P0=table[c];
   dula=1;
   dula=0;
   
   P0=0xfb;
   wela=1;
   wela=0;
   delay(5);
   
   P0=table[d];
   dula=1;
   dula=0;
   
   P0=0xf7;
   wela=1;
   wela=0;
   delay(5);
   
   P0=table[e];
   dula=1;
   dula=0;
   
   P0=0xef;
   wela=1;
   wela=0;
   delay(5);
   
   P0=table[f];
   dula=1;
   dula=0;
   
   P0=0xdf;
   wela=1;
   wela=0;
   delay(5);
}


void keyscan()                                   //矩阵键盘扫描函数
{
  {	
    P3=0xfe;                                     //对第一行赋0,即低电平
    temp=P3;                                     //定义P3口即矩阵口为temp
    temp=temp&0xf0;                              //将temp和0xf0进行“与”运算后再次赋予temp
    if(temp!=0xf0)                               /*如果temp不等于0xf0时,说明第一行有按键被按下,
			                                             下面的检测第一行哪一个被按下的检测函数*/
    {                                            
      delay(10);                                 //按键消抖
      if(temp!=0xf0)                             //再次检测,确保第一行确实有被摁下的按键
      {	
        temp=P3;                               //将P3口的状态赋值给temp
        switch(temp)                        //把temp和下面case后的数值进行比较,如果相同执行相应操作
        {
          case 0xee:                        //如果temp=0xee,那么
	            key=0;                        //那木key=0,
			   wei++;                             //wei加一
               break;                       //退出,再次扫描

          case 0xde:
               key=1;
			   wei++;
               break;

          case 0xbe:
               key=2;                       //同上
			   wei++;
               break;

          case 0x7e:
               key=3;
			   wei++;
               break;
         }
         while(temp!=0xf0)                   //松手检测,只有当temp不等于0xf0时进入,持续扫描
        {
           temp=P3;
           temp=temp&0xf0;
           beep=0;                          //在不松手时蜂鸣器响起
         }
         beep=1;                            //松手后蜂鸣器关闭
      }
    }
    P3=0xfd;                                //对矩阵扫描第二行,方法同第一行
    temp=P3;
    temp=temp&0xf0;
    if(temp!=0xf0)
    {
      delay(10);
      if(temp!=0xf0)
      {
        temp=P3;
        switch(temp)
        {
          case 0xed:
               key=4;
			   wei++;
               break;

          case 0xdd:
               key=5;
			   wei++;
               break;

          case 0xbd:
               key=6;
			   wei++;
               break;

          case 0x7d:
               key=7;
			   wei++;
               break;
         }
         while(temp!=0xf0)
         {
           temp=P3;
           temp=temp&0xf0;
           beep=0;
         }
         beep=1;
      }
      }
    P3=0xfb;                               //对矩阵扫描第三行,方法同第一行
    temp=P3;
    temp=temp&0xf0;
    if(temp!=0xf0)
    {
      delay(10);
      if(temp!=0xf0)
      {
        temp=P3;
        switch(temp)
        {
          case 0xeb:
               key=8;
			   wei++;
               break;

          case 0xdb:
               key=9;
			   wei++;
               break;
	到现在为止0~9十个键已经扫描完成,接下来配置四个功能按键		   
          case 0xbb:                 //如果第三行第3个键被按下,
               genggai=1;            //genggai=1
			   wei=0;                      //将wei归零
               break;

          case 0x7b:                //如果第三行第四个键被按下
		  	   if(allow)                //并且allow等于1时
               ok=1;               //将ok=1
               break;
         }
        while(temp!=0xf0)                 //松手检测
         {
           temp=P3;
           temp=temp&0xf0;             
           beep=0;
         }
         beep=1;
      }
      }
	  P3=0xf7;                           //对第四行进行扫描
    temp=P3;
    temp=temp&0xf0;
    if(temp!=0xf0)
    {
      delay(10);
      if(temp!=0xf0)
      {
        temp=P3;
        switch(temp)
        {
          case 0xe7:                     //如果第四行第一个按键被按下
		  	   retry=1;                      //那木retry=1
               break;

          case 0xd7:                    //如果第四行第二个按键被按下,
		  	   close=1;                     //那么close=1
               break;
         }
        while(temp!=0xf0)
         {
           temp=P3;
           temp=temp&0xf0;
           beep=0;
         }
         beep=1;
      }
      }
}
}

void shumima()		                //对按键采集来的数据进行分配
{                                 //这个子函数分析密码是否输入完成,并且让数码管逐渐亮起来
	if(!wanbi)                      //如果wanbi不等于一,进入这个if循环
	{
	switch(wei)                     //将wei和下面的数值比较,完成相应程序
	{
		case 1:new1=key;                //如果等于一,将key赋值new1,即刚刚按下的值,
			    if(!allow)	a=17;         //如果密码没有输入完成且正确,那么将a赋值17
			   else a=key;	break;        //如果没有完成上面的操作,那木让a=key,这一步是改密码的操作
		case 2:new2=key;                //同上
				if(a==17) b=17;
				else b=key;	break;
		case 3:new3=key; 
				if(a==17) c=17;
				else c=key;	break;
		case 4:new4=key;
				if(a==17) d=17;
				else d=key;	break;
		case 5:new5=key; 
				if(a==17) e=17;
				else e=key;	break;
		case 6:new6=key; 
				if(a==17) f=17;
				else f=key;
				wanbi=1;	break;                 //完成后wanbi=1,所以可以跳出这个while循环
	}
	}
}

void yanzheng()	                  //验证密码是否正确
{
	if(wanbi)	                      //只有当六位密码均输入完毕后方进行验证
	{
	if((new1==old1)&(new2==old2)&(new3==old3)&(new4==old4)&(new5==old5)&(new6==old6))
		allow=1;	                       //当上面全部成立,证明输入的密码正确,会得到allowe=1
	}
}

void main()                  //主函数
{
	while(1)                   //大循环
	{
		keyscan();                //不停的扫描矩阵键盘
		shumima();                //数码管显示子函数
		yanzheng();               //验证密码是否输入正确
		if(allow)	                //验证完后,若allow为1,则开锁
		{
			P1=0x00;                //开锁后的指令,让所有led都亮起来
			if(!genggai)            //如果没有按下更改键,wanbi会被置0
				wanbi=0;                
		}
		if(genggai)	                //当更改密码键被按下,genggai会被置一
		{
			if(allow)	              //判断密码锁是否打开,如果打开,才有更改密码的权限
			{
				while(!wanbi)	         //当新的六位密码没有设定完,则一直在这里循环
				{
				 	keyscan();           //持续扫描
					shumima();
					if(retry|close)	  //当检测到retry或close任意一个被按下,那木会让wanbi=1,即跳出数码管显示子函数
					{	wanbi=1;
						break;
					}
					display(a,b,c,d,e,f);         //更改密码时数码管显示要更改的密码
				}
			}
		}
		if(ok)	   ///更改完成后,按下ok,结束并保存
		{		             //其他时间按下此键无效
			ok=0; wei=0;
			genggai=0;
			old1=new1;old2=new2;old3=new3;       //此时,旧的密码将被代替
			old4=new4;old5=new5;old6=new6;
			a=16;b=16;c=16;d=16;e=16;f=16;
		}
		if(retry)	                      //当retry被按下,相当于重新输入密码,无论是在改密码还是输密码时
		{
		retry=0; wei=0;wanbi=0;
		a=16;b=16;c=16;d=16;e=16;f=16;
		new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;		
		}
		if(close)                    //当close被摁下时,所有密码清零
		{
			close=0;genggai=0;//所有变量均被清零。
			wei=0;	wanbi=0;
			allow=0;
			P1=0xff;
			a=16;b=16;c=16;d=16;e=16;f=16;
			new1=0;new2=0;new3=0;new4=0;new5=0;new6=0;
		}
		display(a,b,c,d,e,f); //实时显示
	}
}

物联沃分享整理
物联沃-IOTWORD物联网 » 基于51单片机的6位密码锁设计(数码管和LED矩阵显示)

发表评论