[51 MCU] 24C02 power-down storage combination lock (comprehensive design report + source program + flow chart)

1 Design goals

Design a combination lock that stores passwords through 24C02 memory chips.

2 main functions

Use the LCD1602 module and independent keys to realize the input and display of the password. The password is stored by the 24C02 memory chip.

3 hardware design

LCD1602 module

 

Independent key module

K1 increase key P3^0

K2 decrease key P3^1

K3 set WRITE key P3^2

K4 set READ key P3^3

24C02

P21 SCL

P20 SDA

4 Software process and code implementation

4.1 Software process

 

 

5 source program

 #include <REGX51.H> 
 //引脚配置:
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
sbit I2C_SCL=P2^1;
sbit I2C_SDA=P2^0;
unsigned char KeyNum;
unsigned int Num;
/**********************************延时函数*************************************************/
 void Delay(unsigned int xms)
{
	unsigned char i, j;
	while(xms--)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
	}
}
/********************************键盘扫描***************************************/
unsigned char Key()	   //按下按键的键码,范围:0~4,无按键按下时返回值为0
{
	unsigned char KeyNumber=0;
	
	if(P3_1==0){Delay(20);while(P3_1==0);Delay(20);KeyNumber=1;}//加 
	if(P3_0==0){Delay(20);while(P3_0==0);Delay(20);KeyNumber=2;}//减 
	if(P3_2==0){Delay(20);while(P3_2==0);Delay(20);KeyNumber=3;}//存 
	if(P3_3==0){Delay(20);while(P3_3==0);Delay(20);KeyNumber=4;}//读 
	
	return KeyNumber;
}
/*******************************I2C函数******************************************/
 
void I2C_Start(void)  //I2C开始
{
	I2C_SDA=1;
	I2C_SCL=1;
	I2C_SDA=0;
	I2C_SCL=0;
}

void I2C_Stop(void)	//I2C停止
{
	I2C_SDA=0;
	I2C_SCL=1;
	I2C_SDA=1;
}

void I2C_SendByte(unsigned char Byte) //I2C发送一个字节	  Byte 要发送的字节
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		I2C_SDA=Byte&(0x80>>i);
		I2C_SCL=1;
		I2C_SCL=0;
	}
}

unsigned char I2C_ReceiveByte(void)//I2C接收一个字节  接收到的一个字节数据
{
	unsigned char i,Byte=0x00;
	I2C_SDA=1;
	for(i=0;i<8;i++)
	{
		I2C_SCL=1;
		if(I2C_SDA){Byte|=(0x80>>i);}
		I2C_SCL=0;
	}
	return Byte;
}

void I2C_SendAck(unsigned char AckBit)//I2C发送应答 AckBit 应答位,0为应答,1为非应答
{
	I2C_SDA=AckBit;
	I2C_SCL=1;
	I2C_SCL=0;
}

unsigned char I2C_ReceiveAck(void)//I2C接收应答位 接收到的应答位,0为应答,1为非应答
{
	unsigned char AckBit;
	I2C_SDA=1;
	I2C_SCL=1;
	AckBit=I2C_SDA;
	I2C_SCL=0;
	return AckBit;
} 
/***************************************************2402*****************************/ 
void AT24C02_WriteByte(unsigned char WordAddress,Data)//AT24C02写入一个字节  WordAddress 要写入字节的地址 Data 要写入的数据
{
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_SendByte(Data);
	I2C_ReceiveAck();
	I2C_Stop();
}

unsigned char AT24C02_ReadByte(unsigned char WordAddress)//AT24C02读取一个字节 WordAddress 要读出字节的地址 Data读出的数据
{
	unsigned char Data;
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS);
	I2C_ReceiveAck();
	I2C_SendByte(WordAddress);
	I2C_ReceiveAck();
	I2C_Start();
	I2C_SendByte(AT24C02_ADDRESS|0x01);
	I2C_ReceiveAck();
	Data=I2C_ReceiveByte();
	I2C_SendAck(1);
	I2C_Stop();
	return Data;
}
/*****************************************1602显示**************************************/
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

void LCD_WriteCommand(unsigned char Command)//LCD1602写命令   Command 要写入的命令 
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_WriteData(unsigned char Data)	//LCD1602写数据	 Data 要写入的数据
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

void LCD_SetCursor(unsigned char Line,unsigned char Column)	 //LCD1602设置光标位置	Line 行位置,范围:1~2	 Column 列位置,范围:1~16
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

void LCD_Init()		//LCD1602初始化函数
{
	LCD_WriteCommand(0x38);//八位数据接口,两行显示,5*7点阵
	LCD_WriteCommand(0x0c);//显示开,光标关,闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后,光标自动加一,画面不动
	LCD_WriteCommand(0x01);//光标复位,清屏
}

void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)// 在LCD1602指定位置开始显示所给字符串	 Line 起始行位置,范围:1~2
{																		//起始列位置,范围:1~16		  String 要显示的字符串
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

int LCD_Pow(int X,int Y)	//返回值=X的Y次方
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length) //在LCD1602指定位置开始显示所给数字	 Line 起始行位置,范围:1~2
{																								   //Column 起始列位置,范围:1~16	  Number 要显示的数字,范围:0~65535
	unsigned char i;																			   // Length 要显示数字的长度,范围:1~5
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

void MODE();
{
  if(KeyNum==1)	//K1按键,Num自增
		{
			Num++;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==2)	//K2按键,Num自减
		{
			Num--;
			LCD_ShowNum(1,1,Num,5);
		}
		if(KeyNum==3)	//K3按键,向AT24C02写入数据
		{
			AT24C02_WriteByte(0,Num%256);//写低8位 ,0地址 
			Delay(5);
			AT24C02_WriteByte(1,Num/256);//写高8位 ,1地址 
			Delay(5);
			LCD_ShowString(2,1,"Write OK");//显示写完了 
			Delay(1000);
			LCD_ShowString(2,1,"        ");//消影 
		}
		if(KeyNum==4)	//K4按键,从AT24C02读取数据
		{
			Num=AT24C02_ReadByte(0);//读低8位 
			Num|=AT24C02_ReadByte(1)<<8;//读高8位 左移8位后或 
			LCD_ShowNum(1,1,Num,5);
			LCD_ShowString(2,1,"Read OK ");
			Delay(1000);
			LCD_ShowString(2,1,"        ");
		}
}
/*********************************主函数*******************************************/
void main()
{
	LCD_Init();//LCD初始化 
	LCD_ShowNum(1,1,Num,5);//第一行第一列展示初始值00000 
	while(1)
	{
		KeyNum=Key();
		MODE(KeyNum); 	
	}
}

6 Conclusion

The programming of LCD1602 and 24c02 mainly adopts the idea of ​​modular programming. Based on the basic working principle, various functions are encapsulated into functions, and then the combination of various functions is realized through function calls, which greatly simplifies the program complexity and readability. , this idea can also be extended to other programs.

Guess you like

Origin blog.csdn.net/m0_57007304/article/details/131493626