C51单片机密码锁课程设计

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

提示:文章写完后,目录可以自动加粗样式生成,如何生成可参考右边的帮助文档


设计要求

微机原理及单片机应用技术的课程设计,C51设计一个密码锁;

要求:键盘上有0-9个数字按键,功能键:确认和取消等,可设置复合键。密码的位数及密码可以任意设定,,当输入数字和设置的密码相同的时候,锁打开,否则无法打开。
基本实现:掉电以后密码不保存,回复初始密码;
提高实现:掉电以后密码不丢失,可由键盘输入任意密码

一、系统模型设计

Proteus仿真图
C51单片机密码锁课程设计
附图为提高实现中的仿真,基础实现的区别在右下角少了一个AT24c02芯片。

二、基础实现

2.1 程序结构

程序主要有四个函数:

void delay()					//延时函数
void display()					//数码管显示函数
void key_scan()					//键盘扫描函数
void main()						//
void time_count() interrupt 1	//中断定时函数

初始化代码:

#include <reg51.h>
#define keyboard P2

unsigned char code table[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
unsigned char code lig[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};			//P1引脚选位
unsigned int code number[4][3]={{7,8,9},{4,5,6},{1,2,3},{0,0,0}};			//键盘查表
unsigned char show[8]={0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf,0xbf};			//数码管只显示show中的内容,数码管默认显示‘横杠’
unsigned char  keywords[21] = {1,2,3,4};						//初始密码
unsigned char input[21] = {0};								//承载输入密码
unsigned char a=0,b,c,d,j,k,temp,key,M,N,clc,enter,change,count=0,number_1=60,z,pp = 3;	//寄存器的定义	**clc,enter,change 这三个我将其称为状态寄存器,当对应按键按下的时候置1;pp密码位数,初始密码更改时要同步更改
signed int num=-1,lock=1;	//lock和上述的clc一样,都是状态寄存器,lock=1时锁定,0解锁;num为密码输入时候的位数辅助计数,注意初始为-1

sbit led1=P3^3;			//红灯--锁定指示灯
sbit led2=P3^4;			//绿灯--解锁指示灯

void delay(unsigned char o)
{
	while(o--);
}

void display()					//8位数码管显示输出
{
		unsigned int i;
		
		for(i=0;i<8;i++)
		{	
			P1 = lig[i];		//多位数码管选位
			P0 = show[i];		//数码管显示内容
			delay(100);
			P0 =0xff;
		}
}

2.2 4×4键盘扫描

键盘扫描代码:

void key_scan()						//键盘按键检测
{	
	P2=0x0f;						
	delay(10);
	if(keyboard == 0x0f)			//a用作按钮松手检测
		a=0;
	if(a == 0)		
	{
		P2=0x0f;
		temp=P2;
		temp=temp&0x0f;
		if(temp!=0x0f)
		{
			delay(10);
			switch(temp)
			{
				case 0x0e:N=0;break;
				case 0x0d:N=1;break;
				case 0x0b:N=2;break;
				case 0x07:N=3;break;
			 }
			P2=0xf0;
			temp=P2;
			temp=temp&0xf0;
			if(temp!=0xf0)
			{
				delay(10);
				switch(temp)
				{
					case 0xe0:M=0;a=1;break;
					case 0xd0:M=1;a=1;break;
					case 0xb0:M=2;a=1;break;
					case 0x70:M=3;a=1;break;
				}
				if(M<3)
				{
					key=number[N][M];		//查表确定按键对应的数
					num++;					//输入位数统计
				}
				else
				{
					switch(N)				//对应最后一列按键
					{
						case 0:change=1;break;		//功能按键置位对应的状态寄存器
						case 1:clc=1;break;
						case 2:enter=1;break;
						case 3:lock=1;break;
					}
				}
			}
		}
	}				

}

2.3 处理函数(数据处理函数)

数据处理的内容都放置在这个函数中

void processing()
{
	if(num>-1)																						//输入input数组转换为显示数组
	{	
		input[num]=key;				//输入密码进入input数组中
		
		if(num>-1 && num<7)			
		{
			show[num]=table[key];	//将输入的密码实时放入show数组中并显示在数码管上;**注意放入show中的是对应显示数字的8位二进制数不是密码本身
		}
		if(num>7 && num != b)
		{
			for(c=0;c<8;c++)
			{
				show[c] = table[input[num-7+c]];	//在密码超出8位后数码管显示内容跟着滚动
			}
		}
		b = num;						//实现每按一次数码管内容刷新一次
	}
	
	if(lock == 1 && enter == 1 )			//在锁定状态下,按确认键开锁
	{
		for(z = 0;z < pp+1;z++)				
		{
			if(input[z] == keywords[z])		//比较输入的密码与设定的是否一致
				d = 1;
			if(input[z] != keywords[z])		
			{
				d = 0;
				break;
			}
		}
		if(pp != num)						//判断密码位数是否一样
			d = 0;
		
		if(d)								//设备解锁
		{
			lock = 0;
			number_1 = 30;					//启动30秒倒计时锁定
		}
		for( z = 0;z<21;z++)				//无论解锁与否都对input和show复位
			{input[z] = 0;}
		for( z = 0;z<8;z++)
			{show[z]=0xbf;}
		num = -1;
		d = 0;
		enter = 0;							//状态寄存器复位
	}
	
	if(clc)									//清除键按下																//清除键
	{
		for( z = 0;z<21;z++)
			{input[z] = 0;}
		for( z = 0;z<8;z++)
			{show[z]=0xbf;}

		num = -1;
		clc = 0;
	}
	if(lock == 0 && change == 1)			//在开锁情况下按更改密码
	{	
		for(z=0;z<21;z++)
		{
			keywords[z] = input[z];
		}
		lock = 1;							//更改密码后设备自动锁定
		for( k = 0;k<8;k++)
			{show[k]=0xbf;}
		for( k = 0;k<21;k++)
			{input[k] = 0;}
		pp = num;							//更改密码位数
		num = -1;
		change = 0;	
	}
	
	if(lock == 0 && number_1 == 0)			//倒计时结束后锁定
		lock = 1;
}

2.4 主函数和中断定时函数

void main()
{	
	EA=1;								//系统初始化寄存器
	ET0=1;
	TMOD=0x01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	TR0=1;
	while(1)
	{
		display();
		key_scan();
		processing();
		if(lock == 1)					//指示灯
		{
			led1 = 0;
			led2 = 1;}
		else
		{
			led1 = 1;
			led2 = 0;}
	}
}

void time_count() interrupt 1		//定时器中断实现延时
{
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	count++;
	if(count==20)
	{
		count=0;
		number_1--;
		if(number_1<0)
			number_1=59;
	}
}

三、提高实现

说明

提高实现在基础实现的基础上有两处的差异。
(1)主函数中系统启动从AT24C02中读取密码放入keywords中;
(2)更改密码时,多了一个密码写入AT24C02的步骤
(3)读写AT24C02的函数编写
附上上述代码

更改密码部分

if(lock == 0 && change == 1)									//在开锁情况下按更改密码
	{	
		number_1 = 20;
		for(z=0;z<8;z++)
		{
			keywords[z] = input[z];
		}
		qq = num;
		
		At24c02Write(0x50, keywords);							//密码写入24C02
		delay(1000);
		
		lock = 1;
		for( k = 0;k<8;k++)
			{show[k]=0xbf;}
		for( k = 0;k<8;k++)
			{input[k] = 0;}
		num = -1;
		change = 0;
	}

主函数部分

void main()							//主程序
{	
	EA=1;							//系统初始化寄存器
	ET0=1;
	IT0=0;
	TMOD=0x01;
	TH0=(65536-50000)/256;
	TL0=(65536-50000)%256;
	TR0=1;
	
//	At24c02Write(0x50, keys);		//keys[]为写入芯片的初始密码,应当在程序开头定义
//	Delay10us();					//用来第一次运行的时候写进24C02(由于AT24C02芯片第一次没有密码数据在里面),在第一次运行后将这两行注释,从新编译一次就可以正常运行
	At24c02Read(keywords,0x50);		//启动读取密码
	
	while(1)
	{
		display();
		key_scan();
		processing();
		if(lock == 1)				//指示灯程序
		{
			led1 = 0;
			led2 = 1;}
		else
		{
			led1 = 1;
			led2 = 0;}
	}
}

AT24C02读写代码

AT24C02的读写89C51没有直接的函数调用,只能自己按照手册通过引脚写通讯函数。
AT24C02的读写下面两篇博客写的很好,想要学习AT24C02的读者可以移步至

https://blog.csdn.net/snyanglq/article/details/50408489?
https://blog.csdn.net/zbl12345678910/article/details/106029054

下面附上读写代码

/**********************************
**	函数名称 :ACK
**	函数功能 : 应答信号
**********************************/
void ACK()			//发送应答A子函数ACK
{
	unsigned char i;
	SCL = 1;		//时钟线发出时钟脉冲
	Delay10us();
	while((SDA == 1) && (i < 200))i++ ;
	SCL = 0;		//与SCL=1组成时钟脉冲
	Delay10us();
}
/**********************************
**	函数名称 :NACK
**	函数功能 : 非应答信号
**********************************/
void NACK()			//发送应答A子函数NACK,见实例354
{

	SDA = 1;		//数据线高电平(发送数据1)
	SCL = 0;
	Delay10us();
	SCL = 1;		//时钟线发出时钟脉冲
	Delay10us();
	SCL = 0;		//与SCL=1组成时钟脉冲
	SDA = 0;		//数据线低电平复位
}
 
/*******************************************************************************
* 函数名         : Start_signal(void)
* 函数功能		 : I2C总线起始信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
 
void I2C_Start_signal(void)
{
	 SDA = 1 ;
	 Delay10us();
	 SCL = 1 ;
	 Delay10us();
	 SDA = 0 ;
	 Delay10us();
	 SCL = 0 ;
	 Delay10us();
}
 
/*******************************************************************************
* 函数名         : Start_signal(void)
* 函数功能		 : I2C总线终止信号
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
 
void I2C_Stop_signal(void)
{
	SDA = 0 ;
	Delay10us();
   	SCL = 1 ;
	Delay10us();
	Delay10us();
	SDA=1;
	Delay10us();
}
 
/*******************************************************************************
* 函数名         : I2C_SendByte(unsigned char dat, unsigned char ack)
* 函数功能		 : I2C总线发送数据
* 输入           : dat,一个字节的数据
* 输出         	 : 发送成功返回1,发送失败返回0
* 备    注       : 发送完一个字节I2C_SCL=0, 需要应答则应答设置为1,否则为0
*******************************************************************************/
 
unsigned char I2C_SendByte(unsigned char dat, unsigned char ack)
{
 
 
 
	unsigned char a = 0,b = 0;//最大255,一个机器周期为1us,最大延时255us。
Replay:
    b = 0 ;			
	for(a=0; a<8; a++)//要发送8位,从最高位开始
	{
		SDA = dat >> 7;	 //起始信号之后I2C_SCL=0,所以可以直接改变I2C_SDA信号
		dat = dat << 1;
		Delay10us();
		SCL = 1;
		Delay10us();//建立时间>4.7us
		SCL = 0;
		Delay10us();//时间大于4us		
	}
 
	SDA = 1;
	Delay10us();
	SCL = 1;
	while(SDA && (ack == 1))//等待应答,也就是等待从设备把I2C_SDA拉低
	{
		b++;
		if(b > 200)	 //如果超过200us没有应答发送失败,或者为非应答,表示接收结束
		{
			SCL = 0;
			Delay10us();
		//	return 0;
			goto Replay ;   //如果超过200us没有应答则发送失败,或者为非应答,这时候系统启动重发机制
							//使用goto语句返回到上面接着发
		}
	}
 
	SCL = 0;
	Delay10us();
 	return 1;		
}
 
/*******************************************************************************
* 函数名         : I2cReadByte()
* 函数功能		 : I2C总线接收数据
* 输入           : 无
* 输出         	 : dat,数据
*******************************************************************************/
 
unsigned char I2cReadByte()
{
	unsigned char a=0,dat=0;
	SDA=1;			
	Delay10us();
	for(a=0;a<8;a++)//接收8个字节
	{
		SCL=1;
		Delay10us();
		dat<<=1;
		dat|=SDA;
		Delay10us();
		SCL=0;
		Delay10us();
	}
	return dat;	
}
 
/*******************************************************************************
* 函数名         : Delay10us()
* 函数功能		 : 延时
* 输入           : 无
* 输出         	 : 无
*******************************************************************************/
 
void Delay10us()
{
   unsigned char a,b;
	for(b=1;b>0;b--)
		for(a=2;a>0;a--);
}
 
/*******************************************************************************
* 函 数 名         : void At24c02Write(unsigned char addr,unsigned char dat)
* 函数功能		   : 往24c02的8个地址写入8个数据
* 输    入         : 地址和数据
* 输    出         : 无
*******************************************************************************/
 
void At24c02Write(unsigned char addr,unsigned char dat[])
{
	unsigned char i;
   	I2C_Start_signal();
	I2C_SendByte(0xa0, 1);//发送写器件地址
	I2C_SendByte(addr, 1);//发送要写入内存地址
	for(i = 0; i < 8; i++)
		I2C_SendByte(dat[i], 0);	//发送数据
	I2C_Stop_signal();
 
}
 
/*******************************************************************************
* 函 数 名         : unsigned char At24c02Read(unsigned char addr)
* 函数功能		   : 读取24c02的一个地址的一个数据
* 输    入         : 无
* 输    出         : 无
*******************************************************************************/


void At24c02Read(unsigned char b[], unsigned char addr)
{
	unsigned char i;
	for(i = 0; i < 7; i++)
	{
		I2C_Start_signal();
		I2C_SendByte(0xa0, 1); 			//发送写器件地址	   1010   0000
		I2C_SendByte(addr + i, 1); 		//发送要读取的地址
		I2C_Start_signal();
		I2C_SendByte(0xa1, 1); 			//发送读器件地址
		b[i] = I2cReadByte();	 		//读取数据
		ACK();	
	}
	I2C_Start_signal();
	I2C_SendByte(0xa0, 1); 				//发送写器件地址	   1010   0000
	I2C_SendByte(addr + i, 1);			 //发送要读取的地址
	I2C_Start_signal();
	I2C_SendByte(0xa1, 1); 				//发送读器件地址
	b[i] =  I2cReadByte();
	NACK();
	I2C_Stop_signal();
	Delay10us();
}

*由于AT24C02读写函数一次只读写8位,所以提高实现中的密码默认只设8位,如果需要更多位密码可以通过多次读取拼接简单实现更多位密码设定。

总结

上述的课程设计完整代码和仿真文件可以下载,文章中没有讲清除的地方可以结合程序进一步理解,希望对各位有所帮助。

https://download.csdn.net/download/canmianlaida/85656284文章来源地址https://www.toymoban.com/news/detail-409795.html

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

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

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

相关文章

  • 51单片机-电子密码锁

    实物演示效果: https://www.bilibili.com/video/BV1xh4y1K7uV/?vd_source=6ff7cd03af95cd504b60511ef9373a1d 电子密码锁的主要功能 1.按键设置6位密码,输入密码若密码正确,则锁打开。显示open! 2.密码可以自己修改(6位密码),必须是锁打开时才能改密。为防止误操作,修改密码得输入两次。

    2024年01月17日
    浏览(45)
  • 51单片机制作简易密码锁

    51单片机期末考试设计题目 设计要求: 设计具有16个按键和1个数码管显示的密码锁,具体要求: 输入一位密码(为0~9,A~F之间的数字),密码输入正确显示“F”并将锁打开;否则显示“E”,继续保持锁定状态。 基本要求: 密码锁的基本功能如下:16个按键,分别代表数

    2024年02月11日
    浏览(48)
  • 51单片机简易电子密码锁

    由于作业需求,在昨天天晚上写了一个通过lcd1602,i2c,eeprom,按键,实现的可以设置密码的简易电子锁,    首先点击k15(回车键)进入  进入后可以点击0-9按键输入6位密码,错误则显示error,5s后重新显示密码输入页面,密码正确则进入。    进入后可以点击Esc键设置密码,进入设

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

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

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

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

    2024年02月03日
    浏览(58)
  • 基于51单片机的电子密码锁

    主要功能: 1、6位密码开锁 可以修改用户密码和管理员密码 断电记忆 3次错误报警锁住键盘

    2024年02月11日
    浏览(47)
  • 基于51单片机的密码锁设计

    电子密码锁设计,以AT89C51为主控,晶振电路和复位电路共同组成最小系统,使得单片机可以正常运行。矩阵按键作为输入模块,输入密码,LCD1602作为显示设备,显示输入的密码和提示语句,AT24C02作为EEPROM存储器,使用LED模拟“锁”,表示锁的开启和关闭状态。系统掉电后,

    2024年02月11日
    浏览(61)
  • 51单片机学习--矩阵键盘、电子密码锁

    矩阵键盘的模块原理图: 功能:按下矩阵按键,在LCD上显示对应的数值。 采用模块化编程,在此只给出MatrixKey.c 和 main.c 两部分代码 这里要注意必须先判断KeyNum是否为0,否则while不断循环会不断显示0,导致看不到按下按钮显示的数字 要利用写好的矩阵键盘来制作一个密码锁

    2024年02月16日
    浏览(56)
  • 基于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)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包