51单片机简易电子密码锁

这篇具有很好参考价值的文章主要介绍了51单片机简易电子密码锁。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

由于作业需求,在昨天天晚上写了一个通过lcd1602,i2c,eeprom,按键,实现的可以设置密码的简易电子锁,

 51单片机简易电子密码锁

 首先点击k15(回车键)进入

51单片机简易电子密码锁51单片机简易电子密码锁

 进入后可以点击0-9按键输入6位密码,错误则显示error,5s后重新显示密码输入页面,密码正确则进入。

 51单片机简易电子密码锁

 进入后可以点击Esc键设置密码,进入设置密码界面

输入密码后显示设置成功并显示新密码 

51单片机简易电子密码锁

main.c文件代码还有待改进,还可以添加功能

首先先要进行多.c文件创建。话不多说,直接上代码。

lcd1602.c

#include <reg52.h>
#define LCD1602_DB P0
sbit LCD1602_RS = P1^0;
sbit LCD1602_RW = P1^1;
sbit LCD1602_E = P1^5;
/* 等待液晶准备好 */
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++);
 } 
}
//写数字
void LcdShowDat(unsigned char x, unsigned char y, unsigned char dat)
{
   LcdSetCursor(x,y);
   LcdWriteDat(dat);
}
/* 区域清除,清除从(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); //清屏
}

 i2c.c

#include <reg52.h>
#include <intrins.h>
#define I2CDelay() {_nop_();_nop_();_nop_();_nop_();}
sbit I2C_SCL = P3^7;
sbit I2C_SDA = P3^6;
/* 产生总线起始信号 */
void I2CStart()
{
 I2C_SDA = 1; //首先确保 SDA、SCL 都是高电平
 I2C_SCL = 1;
 I2CDelay();
 I2C_SDA = 0; //先拉低 SDA
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL
}
/* 产生总线停止信号 */
void I2CStop()
{
 I2C_SCL = 0; //首先确保 SDA、SCL 都是低电平
 I2C_SDA = 0;
 I2CDelay();
 I2C_SCL = 1; //先拉高 SCL
 I2CDelay();
 I2C_SDA = 1; //再拉高 SDA
 I2CDelay();
}
/* I2C 总线写操作,dat-待写入字节,返回值-从机应答位的值 */
bit I2CWrite(unsigned char dat)
{
 bit ack; //用于暂存应答位的值
 unsigned char mask; //用于探测字节内某一位值的掩码变量
 for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
 {
 if ((mask&dat) == 0) //该位的值输出到 SDA 上
 I2C_SDA = 0;
 else
 I2C_SDA = 1;
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL,完成一个位周期
 }
 I2C_SDA = 1; //8 位数据发送完后,主机释放 SDA,以检测从机应答
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 ack = I2C_SDA; //读取此时的 SDA 值,即为从机的应答值
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
 return (~ack); //应答值取反以符合通常的逻辑:
 //0=不存在或忙或写入失败,1=存在且空闲或写入成功
}
/* I2C 总线读操作,并发送非应答信号,返回值-读到的字节 */
unsigned char I2CReadNAK()
{
 unsigned char mask;
 unsigned char dat;
 I2C_SDA = 1; //首先确保主机释放 SDA
 for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
 {
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 if(I2C_SDA == 0) //读取 SDA 的值
 dat &= ~mask; //为 0 时,dat 中对应位清零
 else
 dat |= mask; //为 1 时,dat 中对应位置 1
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
 }
 I2C_SDA = 1; //8 位数据发送完后,拉高 SDA,发送非应答信号
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL 完成非应答位,并保持住总线
 return dat;
}
/* I2C 总线读操作,并发送应答信号,返回值-读到的字节 */
unsigned char I2CReadACK()
{
 unsigned char mask;
 unsigned char dat;
 I2C_SDA = 1; //首先确保主机释放 SDA
 for (mask=0x80; mask!=0; mask>>=1) //从高位到低位依次进行
 {
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 if(I2C_SDA == 0) //读取 SDA 的值
 dat &= ~mask; //为 0 时,dat 中对应位清零
 else
 dat |= mask; //为 1 时,dat 中对应位置 1
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL,以使从机发送出下一位
 }
 I2C_SDA = 0; //8 位数据发送完后,拉低 SDA,发送应答信号
 I2CDelay();
 I2C_SCL = 1; //拉高 SCL
 I2CDelay();
 I2C_SCL = 0; //再拉低 SCL 完成应答位,并保持住总线
 return dat;
}

eeprom.c

#include <reg52.h>
extern void I2CStart();
extern void I2CStop();
extern unsigned char I2CReadACK();
extern unsigned char I2CReadNAK();
extern bit I2CWrite(unsigned char dat);
/* E2 读取函数,buf-数据接收指针,addr-E2 中的起始地址,len-读取长度 */
void E2Read(unsigned char *buf, unsigned char addr, unsigned char len)
{
 do { //用寻址操作查询当前是否可进行读写操作
 I2CStart();
 if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询
 {
 break;
 }
 I2CStop();
 } while(1);
 I2CWrite(addr); //写入起始地址
 I2CStart(); //发送重复启动信号
 I2CWrite((0x50<<1)|0x01); //寻址器件,后续为读操作
 while (len > 1) //连续读取 len-1 个字节
 {
 *buf++ = I2CReadACK(); //最后字节之前为读取操作+应答
 len--;
 }
 *buf = I2CReadNAK(); //最后一个字节为读取操作+非应答
 I2CStop();
}
/* E2 写入函数,buf-源数据指针,addr-E2 中的起始地址,len-写入长度 */
void E2Write(unsigned char *buf, unsigned char addr, unsigned char len)
{
 while (len > 0)
 {
 //等待上次写入操作完成
 do { //用寻址操作查询当前是否可进行读写操作
 I2CStart();
 if (I2CWrite(0x50<<1)) //应答则跳出循环,非应答则进行下一次查询
 {
 break;
 }
 I2CStop();
 } while(1);
 //按页写模式连续写入字节
 I2CWrite(addr); //写入起始地址
 while (len > 0)
 {
 I2CWrite(*buf++); //写入一个字节数据
 len--; //待写入长度计数递减
 addr++; //E2 地址递增
 if ((addr&0x07) == 0) //检查地址是否到达页边界,24C02 每页 8 字节,
 { //所以检测低 3 位是否为零即可
 break; //到达页边界时,跳出循环,结束本次写操作
 }
 }
 I2CStop();
 } }

下面通过函数调用,首先,先建立两个函数

bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)//比较字符串是否相等
{
 while (len--)
 {
 if (*ptr1++ != *ptr2++) //遇到不相等数据时即刻返回 0
 {
 return 0;
 }
 }
 return 1; //比较完全部长度数据都相等则返回 1 }
}

用来比较字符串是否相等

unsigned char key_board()//按键检测,放入while循环
{
   uchar temp; //P2口数据存储
   uchar count;
   uchar num_key=20;      //返回的键值
   static uchar key_old=0xfe;//键盘扫描循环初始值
   static uchar  key_code;

   P2=key_old;
   temp=P2;
 if(temp!=key_old)//判断是否有按键按下
    {
      count++;
      if(count==10)
        {
            F0=1;
            key_code=temp;
        }
    } 
  else
      {
           count=0;
         if(F0==1)
         {
              F0=0;
              switch(key_code)//读出键值
             {
                 //P2^0线设置为低电平 
                  case 0xEE: num_key=10;  break; 
                  case 0xDE: num_key=11;  break;
                  case 0xBE: num_key=12;  break;                                
                  case 0x7E: num_key=13;  break;            
                  //P2^1线设置为低电平 
                  case 0xED: num_key=7;  break;
                  case 0xDD: num_key=8;  break; 
                  case 0xBD: num_key=9;  break; 
                  case 0x7D: num_key=14;  break;                                   
                  //P2^2线 设置为低电平 
                  case 0xEB: num_key=4;  break;
                  case 0xDB: num_key=5; break;                           
                  case 0xBB: num_key=6; break;               
                  case 0x7B: num_key=15; break;   
                  //P2^3线 设置为低电平                                                   
                  case 0xE7: num_key=1; break; 
                  case 0xD7: num_key=2; break;
                  case 0xB7: num_key=3; break;
                  case 0x77: num_key=16; break; 
                                                                                                                                        
               }
              
             }
              
          key_old=_crol_(key_old,1);//改变扫描线 
              if(key_old==0xef)
               {
                  key_old=0xfe;
               }
         }
    return(num_key);    //返回键值
}

按键没有使用定时器,直接通过while循环检测按键,直接调用函数

下面是mian.c函数主要内容

#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
unsigned char buf[4];
extern void LcdWaitReady();
extern void LcdWriteCmd(unsigned char cmd);
extern void LcdWriteDat(unsigned char dat);
extern void LcdSetCursor(unsigned char x, unsigned char y);
extern void LcdShowStr(unsigned char x, unsigned char y, unsigned char *str);
extern void LcdAreaClear(unsigned char x, unsigned char y, unsigned char len);
extern void InitLcd1602();
extern void LcdShowDat(unsigned char x, unsigned char y, unsigned char dat);
extern void E2Write(unsigned char *buf, unsigned char addr, unsigned char len);
extern void E2Read(unsigned char *buf, unsigned char addr, unsigned char len);
bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len);
unsigned char key_board();
unsigned char cnt=0;
unsigned char a[2],b[2]="1",c1=0,c2[10],c3[10],d=0,e=0;
bit f=0,g=0;
void delay_ms(unsigned int i)
{
 unsigned char k;
 while(i--)
{
  for(k=110;k>0;k--);
}
}
void main()
{
    int i=0;
    unsigned char temp;
	unsigned char mm[]="123456";
	unsigned char str[]="HELLO";
	unsigned char str2[]="Set Password";
	unsigned char str1[]="Input Password";
	unsigned char str3[]="yes";
	TMOD=0x01;
	TH0=0x4C;
	TL0=0x00;
	IE=0x82;
	TR0=1;
    E2Write(mm,20,6);
    InitLcd1602();
	LcdShowStr(2,0,str);		 
	while(1)
	{
		c1=key_board();

		if(d==1)
		{ 

		  if(c1<=10)
		  {
		  LcdWriteDat(42);
		  if(c1==10)
		  c2[e]=48;
		  else
		  c2[e]=c1+48;
		  e++;
		  }else if(c1==12&&f==0)
		  {
		   e=0;
		   E2Read(c3,20,6);
		   if(CmpMemory(c2,c3,6)==1)
		   {
		   LcdAreaClear(0,0,16);
		   LcdAreaClear(0,1,16);
		   LcdShowStr(2,0,"right");
		   f=1;
		   }else
		   {
		   LcdAreaClear(0,0,16);
		   LcdAreaClear(0,1,16);
		   LcdShowStr(2,0,"Error");
		   delay_ms(5000);
		   d=0;
		   } 
		  }else if(c1==12&&g==1)
		  {
		   e=0;
		   E2Write(c2,20,6);
		   E2Read(c3,20,6);
		   LcdAreaClear(0,0,16);
		   LcdAreaClear(0,1,16);
		   LcdShowStr(2,0,"set succeeded");
		   LcdShowStr(2,1,c3);
		  }
		}
		  if(c1==12&&d==0)
		{
		LcdShowStr(2,0,str1);
		LcdWriteCmd(0x80+0x40+0x03);
		LcdWriteCmd(0x0f);
		  d=1;
		}
		if(f==1&&c1==11&&g==0)
		{
		   LcdAreaClear(0,0,16);
		   LcdAreaClear(0,1,16);
		   LcdShowStr(2,0,"Input Password");
		   LcdWriteCmd(0x80+0x40+0x03);
		   LcdWriteCmd(0x0f);
		   e=0;
		   g=1;
		}	  
	 	   
	} 	
}
void clock() interrupt 1
{
   cnt++;
   TH0=0x4C;
   TL0=0x00;
   if(cnt>=20)
   {
	 
	 cnt=0;
   }
}

bit CmpMemory(unsigned char *ptr1, unsigned char *ptr2, unsigned char len)//比较字符串是否相等
{
 while (len--)
 {
 if (*ptr1++ != *ptr2++) //遇到不相等数据时即刻返回 0
 {
 return 0;
 }
 }
 return 1; //比较完全部长度数据都相等则返回 1 }
}
unsigned char key_board()//按键检测,放入while循环
{
   uchar temp; //P2口数据存储
   uchar count;
   uchar num_key=20;	  //返回的键值
   static uchar key_old=0xfe;//键盘扫描循环初始值
   static uchar  key_code;

   P2=key_old;
   temp=P2;
 if(temp!=key_old)//判断是否有按键按下
    {
	  count++;
	  if(count==10)
		{
			F0=1;
			key_code=temp;
		}
	} 
  else
      {
  	     count=0;
		 if(F0==1)
		 {
		 	 F0=0;
		 	 switch(key_code)//读出键值
			 {
			     //P2^0线设置为低电平 
                  case 0xEE: num_key=10;  break; 
                  case 0xDE: num_key=11;  break;
                  case 0xBE: num_key=12;  break;                                
                  case 0x7E: num_key=13;  break;            
                  //P2^1线设置为低电平 
                  case 0xED: num_key=7;  break;
                  case 0xDD: num_key=8;  break; 
                  case 0xBD: num_key=9;  break; 
                  case 0x7D: num_key=14;  break;                                   
                  //P2^2线 设置为低电平 
                  case 0xEB: num_key=4;  break;
                  case 0xDB: num_key=5; break;                           
                  case 0xBB: num_key=6; break;               
                  case 0x7B: num_key=15; break;   
                  //P2^3线 设置为低电平                                                   
                  case 0xE7: num_key=1; break; 
                  case 0xD7: num_key=2; break;
                  case 0xB7: num_key=3; break;
                  case 0x77: num_key=16; break; 
                                                                                                                                        
               }
			  
			 }
			  
		  key_old=_crol_(key_old,1);//改变扫描线 
			  if(key_old==0xef)
			   {
			  	key_old=0xfe;
			   }
	     }
	return(num_key);	//返回键值
}

main.c函数里有一些没有用上的值和数组 文章来源地址https://www.toymoban.com/news/detail-433973.html

到了这里,关于51单片机简易电子密码锁的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

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

    一.硬件方案         本系统由STC89C52单片机、4*4矩阵键盘,蜂鸣器,复位电路和晶振电路、继电器等组成,4*4键盘主要用于密码的输入和修改,蜂鸣器报警,复位电路和晶振电路与STC89C52单片机组成单片机最小系统。它具有设置、修改6位用户密码、输错报警、密码错误报

    2024年02月16日
    浏览(47)
  • 【Proteus仿真】【51单片机】电子密码锁设计

    本项目使用Proteus8仿真51单片机控制器,使用LCD1602液晶、矩阵按键、蜂鸣器、EEPROM模块、继电器模块等。 系统运行后,LCD1602显示密码输入提示界面,系统存储在EEPROM的初始密码为123456, 用户可通过矩阵按键S1-S10输入数值0-9,当在密码输入过程中有误,可按S11键回删并重新输

    2024年02月13日
    浏览(41)
  • (含代码)基于51单片机电子密码锁设计

    一.硬件说明 采用STC89C51作为主控芯片,结合矩阵按键输入模块、数码管显示模块、LCD1602液晶显示、LED、蜂鸣器报警器等电路模块实现开锁、上锁、报警、密码更改等功能,设计一款可修改密码且具有报警功能的液晶显示电子密码锁。 主要由STM32单片机+最小系统+LCD1602液晶显

    2024年01月16日
    浏览(50)
  • 基于51单片机LCD1602的简易矩阵键盘密码锁

    初次开始写博客,表达方面也许会有很多不足,希望自己能通过这种方式巩固自己的学习和锻炼表达能力,同时也是对于自己学习的记录。 四位密码锁,密码可更改,输入仅四次以内有效 矩阵键盘定义为1-16,顺序为从左上到右下,1-10号为密码输入键位,对键码取余,输入

    2024年01月23日
    浏览(60)
  • 基于51单片机的简易6位密码锁(数码管 led 矩阵)

      本文章是基于51单片机的简易密码锁,无掉电保护,所以没有用到I^C总线协议,仅用到数码管显示,矩阵键盘扫描,led显示。   本例程主要实现功能为:定义一个六位数的初始密码,用矩阵输入,输入正确后led被点亮,错误不点亮;摁下任意一个按键蜂鸣器发出声音,松下

    2024年02月11日
    浏览(40)
  • 基于AT89C51单片机的电子密码锁设计与仿真

    点击链接获取Keil源码与Project Backups仿真图: https://download.csdn.net/download/qq_64505944/87760996?spm=1001.2014.3001.5503 源码获取 主要内容: (1)本设计为了防止密码被窃取要求在输入密码时在LCD屏幕上显示*号。 (2)设计开锁密码位六位密码的电子密码锁。 (3)能够LCD显示在密码正确

    2024年02月03日
    浏览(51)
  • 51单片机“密码锁”代码详解

    注:此代码一经过验证,读者不必怀疑其正确性,如果烧录进去没有反应,请自行检查引脚端口配置,以及仔细分析代码实现原理。倘若能静下心来分析代码,一定能受益匪浅。 废话不多说,,直接上代码。如有问题,请下方评论并私信我,收到后一定及时回复!     功能

    2024年02月08日
    浏览(53)
  • 基于单片机的电子密码锁设计

    1.设计任务 利用AT89C51单片机为核心控制元件,设计一个简易的电子密码锁,可设置四位密码,输入错误三次,报警灯亮起(红灯亮起),输入正确,绿灯闪烁三次。可通过LCD显示屏查看密码,并可通过特殊键位清除密码。 本系统由AT89C51单片机系统(主要是AT89C51单片机最小系

    2024年02月02日
    浏览(45)
  • 基于单片机智能电子密码锁设计

    ** 单片机设计介绍,基于单片机智能电子密码锁设计   基于单片机的智能电子密码锁设计是一种利用单片机(如Arduino、Raspberry Pi等)和相关电子元件来实现的电子密码锁系统。下面是一个基本设计的介绍: 系统组成: 单片机模块:负责控制和处理密码输入、验证和锁控制

    2024年02月03日
    浏览(61)
  • 51单片机实现矩阵键盘密码锁

    使用51单片机的矩阵键盘模块以及led1602显示屏,实现模拟密码锁。 当程序烧录到单片机中后,led1602屏幕会显示文字。 第一行会显示单词“PASSWORD”,第二行显示4个0,表示我们要写入的四位密码,每位默认为0。 矩阵键盘前两行与第三行的前两个分别代表输入1-9与0,第三行第

    2024年02月03日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包