Design of intelligent electronic code lock based on 51 microcontroller

This topic was written by the author during course design. It has been a while since it was posted on his website. Now that the website resource has expired, it has been saved here.

The question requirements are as follows:

Content and requirements

With the MCS-51 microcontroller as the core, a digital password lock control system is designed for inputting passwords through the panel keyboard. The specific requirements are as follows:

①The password is entered through the panel keyboard and consists of 4 to 6 digits;

② When the entered password matches the key, the 3-phase 6-beat micro stepper motor is controlled to rotate forward to the unlocking sensor and is in place. If it does not match three times, a sound and light alarm will occur;

③ 5 seconds after unlocking, check the door closing sensor. If it is in place, control the 3-phase 6-beat micro stepper motor to rotate forward to lock the door, otherwise an alarm will appear;

④ The key can be updated through the panel keyboard;

⑤ Use LCD to display password input process, password input errors and other related information.

⑥ Expansion and innovation.

The content of this topic is not much. It is to enter the password. If it is correct, the motor will be driven to open the door (only the motor is driven and nothing else is done). After opening the door, it is necessary to detect whether the door is closed and whether it has not been closed for a long time. The proximity switch sensor is used for door closing detection (it is simple to use, and the level will change when metal is near, so it can be operated).

Many of this questions use timing to process some things, which is not very flexible, and the code is somewhat redundant, so there is still a lot of room for improvement.

Without further ado, let’s just put the code, circuit diagram and block diagram.

#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();
  }

Circuit diagram:

 Main program block diagram:

 Video effect display:

IMG_3054

IMG_3052

Guess you like

Origin blog.csdn.net/yoonaanna/article/details/123638470