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

该题目是作者课程设计时所写题目,隔了段时间了,之前一直放到自己的网站上的,现在网站资源过期了,就放到这里保存了。

题目要求如下:

内容及要求

以MCS-51单片机为核心,设计一个通过面板键盘输入密码的数字式密码锁控制系统,具体要求如下:

密码通过面板键盘输入,由4~6位数字组成;

② 输入的密码与密钥相符时,控制3相6拍微型步进电机正转到开锁传感器到位,三次不符时,声光报警;

③ 开锁后5秒,检查关门传感器,若到位则控制3相6拍微型步进电机正转锁门,否则报警提示;

④ 密钥可以通过面板键盘更新;

⑤ 采用液晶显示器显示密码输入过程、密码输入错误等相关信息。

⑥ 拓展与创新。

这个题目的内容也不是很多,就是输入密码,如果正确则驱动电机转动开门(只驱动电机,其他的没搞),还有就是开门后要检测门是否关上以及是否长时间未关门。关门检测使用到了接近开关传感器(使用简单,近距离金属靠近则会有电平变化,就可以进行操作)。

本题目很多都是用到定时去处理一些东西,不是很灵活,而且代码有些冗余,所以改进空间还是很大的。

话不多说直接放代码和电路图以及框图。

#include<reg51.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
#define LCD1602_DATAPINS P0	 //显示屏的定义
#define GPIO_KEY P1
sbit LCD1602_E=P2^7;
sbit LCD1602_RW=P2^5;
sbit LCD1602_RS=P2^6;
sbit LED_GREEN=P2^2;
sbit LED_RED=P2^3;
sbit SPEAKER=P3^3;
sbit JJKG=P3^4;
sbit I2C_SCL = P2^1;
sbit I2C_SDA = P2^0;
sbit motorA = P1^0;
sbit motorB = P1^1;
sbit motorC = P1^2;
sbit motorD = P1^3;
char code table[]="INPUT:";
char code jianzhi[]="0123456789ABCDEF"	;
char code zhebi[]="************* ";
char code baocuo[]="ERROR";
char code dengdai[]="WAIT";
char code zaicishuru[]="INPUT AGAIN";
char code door[]="DOOR IS OPEN"	;
char code xinmima[]="SET SECRETE";
char code successful[]="SUCCESS";
char code Warnning[]="WARNING!";
char code GM[]="ATTENTION";
char code lock[]="------LOCK------" ;
char code ss[]="****************";
char code root[]="ROOT: *****"  ;
//char  kaimen[5]={1,2,3,4,5};
char kaimen[5];
char guanliyuan[5]={1,1,1,1,1};
char cunchumima[5];
char tz_flag;
uchar gm_flag=0;
uchar cuowu_flag=0;
uchar pd_flag;
uchar xunhuancishu;
uchar s=0;
uchar sp_flag=0;
uchar ks_flag=1;
uchar gl_flag=0;
uchar tiaozhuan_flag=0;
int data num[5];
uchar km_flag=1;
uchar n;
uchar i;
uchar k;
uchar m=0;
uchar j;
uchar r;
uchar guanmenjishi;
uchar password[5];
uint hang;
uint lie;
uint _flag_=0,cp=0;
void Delay1ms(uint c);   
void Read_Busy() ;
void write_data(uchar date)	; //LCD1602写入8位命令子函数
void write_com(uchar com)    ;  //LCD1602写入8位数据子函数  
void init();			//LCD1602初始化子程序
uint count(uint hang,uint lie);
void tishixinxi();
void addr_x_y(uint x,uint y);
void display(uint x,uint y,uint z);
void mimadisplay();
void keyboard(); //键盘按键扫描函数
void chenggong();
void shibai();
void mima();
void xiugaimima();
void JG();
void fanzhuan();
void guanmenbaojin();
void spchengxu();
void delay(uint t) ;
void zhengzhuan();



//--声明全局变量--//
void I2C_Delay10us();
void I2C_Start();           //起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Stop();            //终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
uchar I2C_SendByte(uchar dat, uchar ack);//使用I2c读取一个字节
uchar I2C_ReadByte();       //通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间,保持发送信号I2C_SDA保持稳定

/*********************IIC.c*************************************/

//延时:1us
void timer_init()
{
	TMOD=0x01;
	TL0=0xb0;
	TH0=0x3c;
	ET0=1;
	EA=1;
}
void timer_1() interrupt 1
{
	TL0=0xb0;
	TH0=0x3c;
	cp++;
	if(cp==100){
		cp=0;
		_flag_=1;
	}
	TR0=1;
}
void I2C_Delay10us()
{
	uchar a, b;
	for(b=1; b>0; b--)
	{
		for(a=2; a>0; a--);
	}
}

// 起始信号:在I2C_SCL时钟信号在高电平期间I2C_SDA信号产生一个下降沿
void I2C_Start()
{
	I2C_SDA = 1;
	I2C_Delay10us();
	I2C_SCL = 1;
	I2C_Delay10us();//建立时间是I2C_SDA保持时间>4.7us
	I2C_SDA = 0;
	I2C_Delay10us();//保持时间是>4us
	I2C_SCL = 0;			
	I2C_Delay10us();		
}

//终止信号:在I2C_SCL时钟信号高电平期间I2C_SDA信号产生一个上升沿
void I2C_Stop()
{
	I2C_SDA = 0;
	I2C_Delay10us();
	I2C_SCL = 1;
	I2C_Delay10us();//建立时间大于4.7us
	I2C_SDA = 1;
	I2C_Delay10us();		
}

//通过I2C发送一个字节。在I2C_SCL时钟信号高电平期间, 保持发送信号I2C_SDA保持稳定
uchar I2C_SendByte(uchar dat, uchar ack)
{
	uchar a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。			
	for(a=0; a<8; a++)//要发送8位,从最高位开始
	{
		I2C_SDA = dat >> 7;	 //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
		dat = dat << 1;
		I2C_Delay10us();
		I2C_SCL = 1;
		I2C_Delay10us();//建立时间>4.7us
		I2C_SCL = 0;
		I2C_Delay10us();//时间大于4us		
	}
	I2C_SDA = 1;
	I2C_Delay10us();
	I2C_SCL = 1;
	while(I2C_SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
	{
		b++;
		if(b > 200)	 //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
		{
			I2C_SCL = 0;
			I2C_Delay10us();
			return 0;
		}
	}
	I2C_SCL = 0;
	I2C_Delay10us();
 	return 1;		
}

// 使用I2c读取一个字节
uchar I2C_ReadByte()
{
	uchar a = 0,dat = 0;
	I2C_SDA = 1;			//起始和发送一个字节之后I2C_SCL都是0
	I2C_Delay10us();
	for(a=0; a<8; a++)//接收8个字节
	{
		I2C_SCL = 1;
		I2C_Delay10us();
		dat <<= 1;
		dat |= I2C_SDA;
		I2C_Delay10us();
		I2C_SCL = 0;
		I2C_Delay10us();
	}
	return dat;		
}

 //函数功能		   : 往24c02的一个地址写入一个数据

void At24c02Write(unsigned char addr,unsigned char dat)
{
	I2C_Start();
	I2C_SendByte(0xa0, 1);//发送写器件地址
	I2C_SendByte(addr, 1);//发送要写入内存地址
	I2C_SendByte(dat, 0);	//发送数据
	I2C_Stop();
}
// 读取24c02的一个地址的一个数据

unsigned char At24c02Read(unsigned char addr)
{
	unsigned char num;
	I2C_Start();
	I2C_SendByte(0xa0, 1); //发送写器件地址
	I2C_SendByte(addr, 1); //发送要读取的地址
	I2C_Start();
	I2C_SendByte(0xa1, 1); //发送读器件地址
	num=I2C_ReadByte(); //读取数据
	I2C_Stop();
	return num;	
}





void Delay1ms(uint c)   
{
    uchar a,b;
    for (; c>0; c--)
    {
         for (b=199;b>0;b--)
         {
            for(a=1;a>0;a--);
         }
    }

}
 
void Read_Busy()		
{
   uchar busy;
   P0 = 0xff;
   LCD1602_RS = 0;
   LCD1602_RW = 1;
   do
    {
          LCD1602_E = 1;
          busy = P0;
          LCD1602_E = 0;
    }while(busy & 0x80);
}

void write_com(uchar com)	 //写入命令
{
Read_Busy();//判断忙
LCD1602_E=0;
LCD1602_RS=0;
LCD1602_RW=0;
P0=com;
Delay1ms(5);
LCD1602_E=1;
Delay1ms(5);
LCD1602_E=0;
}
void write_data(uchar date)	  //写入数据
{
Read_Busy();//判断忙
LCD1602_E=0;
LCD1602_RS=1;
LCD1602_RW=0;
P0=date;
Delay1ms(5);
LCD1602_E=1;
Delay1ms(5);
LCD1602_E=0;
}
void init()	//LCD初始化子程序
{
Delay1ms(5);
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
}					//1602显示

 
void keyboard() //键盘按键扫描函数
  {
  GPIO_KEY = 0x0f;
  if(GPIO_KEY != 0x0f)//检测4行中哪一行按键是否按下
  {
   Delay1ms(10);  //延时消抖
   if(GPIO_KEY != 0x0f) //再次检测4行中哪一行按键是否按下
   {
   switch(GPIO_KEY) //根据IO的值来确定哪一行按键按下
   {
   case(0x07): lie=1; break;
   case(0x0b): lie=2; break;
   case(0x0d): lie=3; break;
   case(0x0e): lie=4; break;
   }
   }
  }
 
  GPIO_KEY = 0xf0;
  if(GPIO_KEY != 0xf0) //检测4列中哪一列按键是否按下
  {
   Delay1ms(10);  //延时消抖
   if(GPIO_KEY != 0xf0) //再次检测4列中哪一列按键是否按下
   {
   switch(GPIO_KEY) //根据IO的值来确定哪一列按键按下
   {
   case(0x70): hang=4; break;
   case(0xb0): hang=3; break;
   case(0xd0): hang=2; break;
   case(0xe0): hang=1; break;
   }
   } 
   while((i<50)&&(GPIO_KEY != 0xf0))				
  {
	i++;
   Delay1ms(10);
  }
   i=0;
   }
   num[m]=count(hang,lie);
   if(num[m]==10)
   xiugaimima();
   m++;
    }


uint count(uint hang,uint lie)
{
if(hang==1&&lie==1)
n=15;
if(hang==1&&lie==2)
n=0;
if(hang==1&&lie==3)
n=14;
if(hang==1&&lie==4)
n=13;
if(hang==2&&lie==1)
n=1;
if(hang==2&&lie==2)
n=2;
if(hang==2&&lie==3)
n=3;
if(hang==2&&lie==4)
n=12;
if(hang==3&&lie==1)
n=4;
if(hang==3&&lie==2)
n=5;
if(hang==3&&lie==3)
n=6;
if(hang==3&&lie==4)
n=11;
if(hang==4&&lie==1)
n=7;
if(hang==4&&lie==2)
n=8;
if(hang==4&&lie==3)
n=9;
if(hang==4&&lie==4)
n=10;
return n;
}
void tishixinxi()
{
init();
write_com(0x80);
for(i=0;i<6;i++)
write_data(table[i]);
write_com(0x80+7);
for(i=0;i<5;i++)
write_data(zhebi[i]);
}
void mima()
{
if(pd_flag==1)	 {
   j=0;
   m=0;
   if(km_flag==1)
   chenggong();
   if(km_flag==0)
   shibai(); 
                 }
}
 void addr_x_y(uint x,uint y)   //列,行,写坐标,定位置
{ 
   uchar temp=0x80;
    if(y)
   {
       temp|=0x40;
   }
       temp|=x;
       write_com(temp);
}
void display(uint x,uint y,uint z)  //显示数字
{ 
     addr_x_y(x,y);
     write_data(z+0x30);
}


void mimadisplay()	//密码显示
{
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
     {
keyboard();
password[j]=num[j];
display(j+7,0,password[j]);	//显示输入的密码
if(password[j]!=kaimen[j])
km_flag=0;	
 j++;
    }
 }
 pd_flag=1;
 mima();
          } 

void main()	 //*****************************************************************************
{
timer_init();
tishixinxi();

for(i=0;i<5;i++){
cunchumima[i]=At24c02Read(0x02+i) ;		 
Delay1ms(10);
}


for(i=0;i<5;i++)
kaimen[i]=cunchumima[i];	 	

Delay1ms(5);
while(1){
mimadisplay()  ;
        }
}


void chenggong()  //*************************
{
init();
write_com(0x80+5);
Delay1ms(5);
for(i=0;i<4;i++)
{
write_data(dengdai[i]);
Delay1ms(5);
}
zhengzhuan();
}
void shibai() //********************
{
init();
cuowu_flag++;
sp_flag++;
if(cuowu_flag==3)
JG();
write_com(0x80);
for(i=0;i<5;i++)
write_data(baocuo[i]);
Delay1ms(100);
if(sp_flag==5)
spchengxu();
write_com(0x80+0x40);
for(i=0;i<11;i++)
write_data(zaicishuru[i]);
LED_RED=0;
Delay1ms(1000);
LED_RED=1;
km_flag=1;
tishixinxi();
mimadisplay();
}
void xiugaimima()
{ 
init();
j=0;
write_com(0x80);
for(i=0;i<11;i++)
write_data(xinmima[i]);
Delay1ms(500);
do //*******************************************************
   {  		ks_flag=1;
   			j=0;
			m=0;
			      init();
    write_com(0x80);
     for(i=0;i<11;i++)
    write_data(root[i]) ;
	Delay1ms(10);
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
     {
keyboard();
Delay1ms(10);
password[j]=num[j];
display(j+6,0,password[j]);	//显示输入的密码
if(password[j]!=guanliyuan[j])
ks_flag=0;	
 j++;
    }
 }

	
   if(ks_flag==1)
   break;
  }while(1)	;//*************************************** 
  Delay1ms(500);
  j=0;
  m=0;
init();
for(i=0;i<6;i++)
write_data(table[i]);
while(j<5)
  {GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
    {
keyboard();
password[j]=num[j];
display(j+7,0,password[j]);	//显示输入的密码	
 At24c02Write(0x02+j,password[j]);
	Delay1ms(10);
	 kaimen[j]=password[j];
 j++;
    }
  }
init();
Delay1ms(200);
write_com(0x80);
for(i=0;i<7;i++)
write_data(successful[i]);
LED_GREEN=0;
LED_RED=0;
Delay1ms(500);
LED_GREEN=1;
LED_RED=1;
tishixinxi();
Delay1ms(300);
  j=0;
  m=0;
mimadisplay();
}
void JG()
{ 
 for(xunhuancishu=0;xunhuancishu<5;xunhuancishu++)
 {
  init();
  write_com(0x80+5);
  for(i=0;i<5;i++)
  write_data(baocuo[i]);
  SPEAKER=0;
  LED_RED=0;
  Delay1ms(500);
  init();
  SPEAKER=1;
  LED_RED=1;
  Delay1ms(100);
  write_com(0x80+4);
  for(i=0;i<8;i++)
  write_data(Warnning[i]);
  SPEAKER=0;
  LED_RED=0;
  Delay1ms(500);
 }
  SPEAKER=1;
  LED_RED=1;
  km_flag=1;
  cuowu_flag=0;
  tishixinxi();
  mimadisplay();

}
void guanmenbaojin()
{
  for(xunhuancishu=0;xunhuancishu<5;xunhuancishu++)
 {
  if(JJKG==0)
  {
  SPEAKER=1;
  break;
  }
  init();
  write_com(0x80+5);
  for(i=0;i<9;i++)
  write_data(GM[i]);
  SPEAKER=0;
  LED_RED=0;
  Delay1ms(500);
  if(JJKG==0)
  {
  SPEAKER=1;
  break;
  }
  init();
  SPEAKER=1;
  LED_RED=1;
  Delay1ms(100);
  write_com(0x80+4);
  for(i=0;i<8;i++)
  write_data(Warnning[i]);
  SPEAKER=0;
  LED_RED=0;
  Delay1ms(1000);
  if(JJKG==0)
  {
  SPEAKER=1;
  break;
  }
 }
  while(1)
  {
   if(JJKG==0)
   {
    uint q; 
   motorA = 0;
   motorB = 0;
   motorC = 0;
   motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
   for(q=0;q<4;q++)
   {
   for(r=0;r<150;r++)
   {
		for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
		{
		motorD = 1;
		motorA = 1;
		delay(20);
		}           //AB通电1ms
		motorD = 0;
		motorA = 0; //AB关电
		for(i = 1;i < 10; ++i)
		{
		motorC = 1;
		motorD = 1;
		delay(20);
		}//BC通电1ms
		motorC = 0;
		motorD = 0;	 //BC关电
		for(i = 1;i < 10; ++i)
		{
		motorB = 1;
		motorC = 1;
		delay(20);//CD通电1ms
		}
		motorB = 0;
		motorC = 0;//CD关电
		for(i = 1;i < 10; ++i)
		{
		motorA = 1;
		motorB = 1;
		delay(20);//DA通电1ms
		}
		motorA = 0;
		motorB = 0;//DA关电

      } 
	  }  
  	      motorA = 1;
   motorB = 1;
   motorC = 1;
   motorD = 1;
   break;
   
   
   
   }
  
  }
   


   
  SPEAKER=1;
  LED_RED=1;
  km_flag=1;
  gm_flag=1;
  cuowu_flag=0;
  tishixinxi();
  mimadisplay();

}


void spchengxu()
{
   init();
   Delay1ms(20);
   write_com(0x80);
   for(i=0;i<16;i++)
   write_data(lock[i]);
   Delay1ms(10);
   write_com(0x80+0x40);
   for(i=0;i<16;i++)
   write_data(ss[i]);
   Delay1ms(10);
 while(1)
{
j=0;
m=0;
while(j<1)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
     {
keyboard();
password[j]=num[j];	
if(password[j]==14)
gl_flag=1;	
 j++;
    }
 }

	Delay1ms(10);
	if(gl_flag==1)
	break;
} 
    init();
    write_com(0x80);
     for(i=0;i<11;i++)
    write_data(root[i]) ;
	Delay1ms(10);
	write_com(0x80+0x40);
	for(i=0;i<16;i++)
	write_data(lock[i]);
	Delay1ms(500);	





do
   {  		ks_flag=1;
   			j=0;
			m=0;
while(j<5)
{
GPIO_KEY = 0x0f;
if(GPIO_KEY != 0x0f&&m<5)
     {
keyboard();
Delay1ms(10);
password[j]=num[j];
display(j+6,0,password[j]);	//显示输入的密码
if(password[j]!=guanliyuan[j])
ks_flag=0;	
 j++;
    }
 }

      init();
    write_com(0x80);
     for(i=0;i<11;i++)
    write_data(root[i]) ;
	Delay1ms(10);
	write_com(0x80+0x40);
	for(i=0;i<16;i++)
	write_data(lock[i]);	
    Delay1ms(10);
   if(ks_flag==1)
   break;
  }while(1)	;

      j=0;
    m=0;
   SPEAKER=1;
  LED_RED=1;
  km_flag=1;
  gm_flag=0;
  ks_flag=1;
  gl_flag=0;
  sp_flag=0;
  cuowu_flag=0;
  tishixinxi();
  mimadisplay();  

}

 void delay(uint t)
{
   while(t--);
}


 void fanzhuan()
{
   uint q; 
   motorA = 0;
   motorB = 0;
   motorC = 0;
   motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
   for(q=0;q<4;q++)
   {
   for(r=0;r<150;r++)
   {
		for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
		{
		motorD = 1;
		motorA = 1;
		delay(20);
		}           //AB通电1ms
		motorD = 0;
		motorA = 0; //AB关电
		for(i = 1;i < 10; ++i)
		{
		motorC = 1;
		motorD = 1;
		delay(20);
		}//BC通电1ms
		motorC = 0;
		motorD = 0;	 //BC关电
		for(i = 1;i < 10; ++i)
		{
		motorB = 1;
		motorC = 1;
		delay(20);//CD通电1ms
		}
		motorB = 0;
		motorC = 0;//CD关电
		for(i = 1;i < 10; ++i)
		{
		motorA = 1;
		motorB = 1;
		delay(20);//DA通电1ms
		}
		motorA = 0;
		motorB = 0;//DA关电

      } 
	  }  
  	      motorA = 1;
   motorB = 1;
   motorC = 1;
   motorD = 1;
   mimadisplay();
  }
void zhengzhuan()
  {
   uint q;
   motorA = 0;
   motorB = 0;
   motorC = 0;
   motorD = 0;//因为P1口管脚复位初始默认高电平(内外都接有上拉电阻),本人先将四相电位置低电平
   for(q=0;q<4;q++)
   {
  for(r=0;r<150;r++)
   {
		for(i = 1;i < 10; ++i)//用for循环实现几秒以上的延时函数,用while循环不能实现
		{
		motorA = 1;
		motorB = 1;
		delay(20);
		}           //AB通电1ms
		motorA = 0;
		motorB = 0; //AB关电
		for(i = 1;i < 10; ++i)
		{
		motorB = 1;
		motorC = 1;
		delay(20);
		}//BC通电1ms
		motorB = 0;
		motorC = 0;	 //BC关电
		for(i = 1;i < 10; ++i)
		{
		motorC = 1;
		motorD = 1;
		delay(20);//CD通电1ms
		}
		motorC = 0;
		motorD = 0;//CD关电
		for(i = 1;i < 10; ++i)
		{
		motorD = 1;
		motorA = 1;
		delay(20);//DA通电1ms
		}
		motorD = 0;
		motorA = 0;//DA关电
   } }
    motorA = 1;
   motorB = 1;
   motorC = 1;
   motorD = 1;
   init();
write_com(0x80);
for(i=0;i<12;i++)
write_data(door[i]);
LED_GREEN=0;
Delay1ms(2000);
LED_GREEN=1;
cuowu_flag=0;
km_flag=1;
tishixinxi();
timer_init();
TR0=1;
while(1){
	if(_flag_==1){
		TR0=0;
		_flag_=0;
		break;
	}
	else if(JJKG==0) {
		TR0=0;
		break;
	}
}
/*for(i=0;i<200;i++)
{
Delay1ms(10);

} */
if(JJKG==0)	fanzhuan();
if(JJKG!=0)	guanmenbaojin();
mimadisplay();
  }

电路图:

 主程序框图:

 视频效果展示:

IMG_3054

IMG_3052

猜你喜欢

转载自blog.csdn.net/yoonaanna/article/details/123638470