基于STC15系列单片机的智能门锁(含IIC、步进电机、矩阵按键、PCF8263、LCD1602等配置文件)

一、项目背景及功能需求

1.1项目背景

智能门锁是一种智能化、高效、安全的门锁,它可以实现密码识别开锁方式,极大地提高了门锁的安全性和便利性。随着人们对安全性的要求越来越高,智能门锁已经成为了现代家庭和企业的必备设备。因此,本项目旨在设计一款基于STC15单片机的智能门锁,以满足人们对安全性和便利性的需求。

1.2 功能需求

从功能上来看,主要分为四个部分:显示时间、密码门锁、修改密码和计算器。其中显示时间可以实时获取当前时间日期;密码门锁不仅可以防盗,还能防止用户忘记带钥匙;修改密码可以让用户在密码泄露时及时更改密码;计算器为创新功能,可以进行一些简单的算术运算。其具体的功能架构如下:

用到的文件模块如下:

(1)显示学号:开始会显示“WelcomeSmartLock”和自己的学号

(2)显示时间:可以实时获取当前日期,星期,时间

(3)密码门锁:输入正确密码即可进行开锁,密码错误3次就会发出警报

(4)修改密码:当门锁打开时才能进行修改密码,修改的密码还需要确认重新输入一次,防止用户输错,只有当两次输入一样,才能进行密码的修改;

(5)计算器:可以进行简单的算数运算

(6)结尾有一个动画页面

二、实训环境

单片机开发板套件、Keil C51、STC-ISP

三、项目硬件搭建

3.1硬件设备

硬件部分包括单片机最小系统、矩阵按键、LCD1602、RTC、步进电机等模块,系统框图如下图所示。

3.2硬件连接电路图

 

 3.3硬件搭建实物图

四、具体任务及内容

完成一个智能门锁,包括以下内容:首先使用软件STC-ISP自动生成所需要延时的秒数,完成延时模块的设计,然后进行LCD1062模块的配置,写好显示函数,可以再液晶屏上显示自己想要的内容;然后用取模软件生成想要的图像,使得液晶屏上能显示开锁和关锁的图像;然后完成4x4矩阵键盘的配置,能够识别哪个键盘按下,并且读入相应的信息;然后完成电机驱动模块的配置,由于单片机电压不足,于是需要引入该模块来调动电机,能够进行门锁的开关。然后进行IIC模块的配置,使得单片机能进行简单的通信;随后进行PCF8263模块的配置,能够进行时间的发送与接收,实时获取当前时间。

五、项目运行说明及截图

通过三天的努力,我成功实现了并创新了这次的智能门锁。智慧门锁从功能上来看,主要分为四个部分:显示时间,密码门锁,修改密码,计算器。其中显示时间可以实时读取显示当前时间;密码门锁只有输入正确密码才会开门,输错3次后会报警;修改密码只有开门后才有权限进行修改,并且需要输入两次一样的要修改的密码才会修改成功;计算器是附加的创新功能,可以进行简单的算术运算。

具体功能体现如下:

进入界面

时间显示界面

门锁界面

修改密码

(没开锁)

(已开锁)

 

计算器界面

动画界面

七、附录:(其他相关技术文档或程序实现源码)

main.c文件

#include <stc15.h>
#include <string.h>
#include "LCD1602.h"
#include "delay.h"
#include "zimo.h"
#include "Key16.h"
#include "stepmotor.h"
#include "PCF8563.h"
#include "JiSuanQi.h"
#define uchar unsigned char
#define uint unsigned int
sbit beep=P3^7;

uint X=999;
uchar clear[]="                ";
uchar clearPwd[]="          ";
uchar show1[]="WelcomeSmartLock";
uchar show2[]="InputPassword";
uchar success_show[]="Success!";
uchar fail_show[]="Fail!";
uchar number[]="211071085";
extern unsigned char time_buf1[8];
extern unsigned char time_buf[8];

uchar PWD[]="888888";
uchar input_Pwd[8];

uchar oneInput[8];
uchar twoInput[8];

uchar JiSuan[10];
uint ans;

uchar clockFlag=0;
uint Motor_Num;
uchar my_input=0;
uchar index=0;
uchar pageFlag=0;
uchar Flag=0;//行
uchar FailNum=0;

void LCD_Show_closeClock();
void LCD_Show_openClock();
void LCD_Clear();
void openClock();
void close();
void LCD_Show_Time();
void Show_Xin();
void main()
{

P3M0=0x00;
P3M1=0x00;
	LCD_Init();
//	time_init();
	LCD_Show_String(0,0,show1);
	LCD_Show_String(3,1,number);
	Delay1000ms();
	LCD_Clear();
	
	while(1)
	{
		my_input = KeyScan_4x4();
		if(my_input=='/')
		{
			pageFlag=(pageFlag+1)%5;
			LCD_Clear();
			Delay200ms();
		}
		if(pageFlag==0)//页面1显示时间
		{
			LCD_Show_Time();
		}
		else if(pageFlag==1)//页面2显示门锁
		{
			if(clockFlag==0)
			{
				LCD_Show_closeClock();
				LCD_Show_String(0,0,show2);
			}
			else if(clockFlag==1)
			{
				LCD_Show_openClock();
			}
			if('0'<=my_input && my_input<='9' && index<=7)
			{
				input_Pwd[index]=my_input;
				LCD_Show_OneChar(index, 1, input_Pwd[index]);
				Delay200ms();
				LCD_Show_OneChar(index, 1, '*');
				index++;
				LCD_Show_OneChar(14, 1, index+'0');
			}
			if(my_input=='<' && index!=0)
			{
				index--;
				input_Pwd[index]='0';
				LCD_Show_OneChar(index, 1, ' ');
				Delay200ms();
				LCD_Show_OneChar(14, 1, index+'0');
			}
			
			if(my_input=='=')
			{
				LCD_Clear();
				input_Pwd[index]='\0';
				index=0;
				if(strcmp(input_Pwd,PWD)==0 && clockFlag==0)
				{
					LCD_Show_String(0,0,success_show);
					openClock();
					Delay1000ms();
					LCD_Clear();
					clockFlag=1;
					LCD_Show_openClock();
					input_Pwd[0]='\0';
					
				}
				else
				{
					LCD_Show_String(0,0,fail_show);
					FailNum++;
					if(FailNum==3)
					{X=999;
						while(X--)
						{
							beep=0;
							Delay500us();
							beep=1;
							Delay500us();
						}
						FailNum=0;
					}
						
					Delay1000ms();
					LCD_Clear();
					LCD_Show_closeClock();
					LCD_Show_String(0,0,show2);
				}
				LCD_Show_OneChar(14, 1, index+'0');
			}
			if(my_input=='+' && clockFlag==1)
			{
				clockFlag=0;
				LCD_Clear();
				Delay200ms();
				index=0;
				close();
				LCD_Show_String(0,0,show2);
				input_Pwd[0]='\0';
				LCD_Show_OneChar(14, 1, index+'0');
			}
			if(my_input=='C')
			{
				LCD_Show_String(0,1,clearPwd);
				Delay200ms();
				index=0;
				LCD_Show_OneChar(14, 1, index+'0');
			}

		}
		else if(pageFlag==2)//页面3显示修改密码
		{
			if(clockFlag==1)
			{
//				LCD_Show_String(0,0,"ChangePassword!");
//				Delay1000ms();
				LCD_Show_String(0,0,"ChangeP");
				LCD_Show_String(0,1,"RepeatP");
				LCD_Show_OneChar(7, Flag, ':');
				if('0'<=my_input && my_input<='9' && index<=7)
				{
					oneInput[index]=my_input;
					LCD_Show_OneChar(index+8, Flag, oneInput[index]);
					Delay200ms();
					LCD_Show_OneChar(index+8, Flag, '*');
					index++;
				}
				if(my_input=='<' && index!=0)
				{
					index--;
					oneInput[index]='0';
					LCD_Show_OneChar(index+8, Flag, ' ');
					Delay200ms();
				}
				if(my_input=='=')
				{
					Delay200ms();
					Flag++;
					oneInput[index]='\0';
					if(Flag==2)
					{
						if(strcmp(oneInput,twoInput)==0)
						{
							strcpy(PWD,oneInput);
							LCD_Clear();
							LCD_Show_String(0,0,"ChangeSuccess!");
							Delay1000ms();
							LCD_Clear();
						}
						else
						{
							LCD_Clear();
							LCD_Show_String(0,0,"DifferentResults!");
							Delay1000ms();
							LCD_Clear();
						}
					}
					strcpy(twoInput, oneInput);
					index=0;
					
				}
			}
			else
			{
				LCD_Show_String(0,0,"  NoAuthority!");
			}
		}
		
		else if(pageFlag==3)//页面4计算器
		{
			if(('0'<=my_input && my_input<='9')||(my_input=='+' || my_input=='-' || my_input=='x' || my_input=='='))
			{
				JiSuan[index]=my_input;
				LCD_Show_OneChar(index, 0, JiSuan[index]);
				index++;
				JiSuan[index]='\0';
				Delay200ms();
				if(my_input=='=')
				{
					ans=Jfuntion(JiSuan);
					LCD_Show_OneChar(0, 1, ans+'0');
				}
			}
			if(my_input=='C')
			{
				LCD_Clear();
				Delay200ms();
				index=0;
			}
			if(my_input=='<' && index!=0)
			{
				index--;
				JiSuan[index]='0';
				LCD_Show_OneChar(index, 0, ' ');
				Delay200ms();
			}
			
			
			
		}
		else if(pageFlag==4)//页面5显示动画
		{
			Show_Xin();
		}
	}
	
}

void LCD_Clear()
{
		LCD_Show_String(0,0,clear);
		LCD_Show_String(0,1,clear);
}
void LCD_Show_closeClock()
{
	LCD_Show_Customer(15,0,0,close_Clock);
	LCD_Show_Customer(15,1,1,guan);

}
void LCD_Show_openClock()
{
		LCD_Show_Customer(15,0,0,open_Clock);
		LCD_Show_Customer(15,1,1,kai);
}
void close()
{
	LCD_Show_closeClock();
	Motor_Num=256;
	while(Motor_Num--)
	{
			Motor_Drive41(0,5);
	}
	MotorStop();
}
void openClock()
{
	Motor_Num=256;
	LCD_Show_openClock();
	while(Motor_Num--)
	{
			Motor_Drive41(1,5);
	}
	MotorStop();
}

void LCD_Show_Time()
{
	//显示年份
	uchar time_ge,time_shi;
	get_time();
	time_ge=time_buf1[1]%10;
	time_shi=time_buf1[1]/10;
	LCD_Show_OneChar(3,0,'2');
	LCD_Show_OneChar(4,0,'0');
	LCD_Show_OneChar(5,0,time_shi+'0');
	LCD_Show_OneChar(6,0,time_ge+'0');
	//显示月份
	time_ge=time_buf1[2]%10;
	time_shi=time_buf1[2]/10;
	LCD_Show_OneChar(8,0,time_shi+'0');
	LCD_Show_OneChar(9,0,time_ge+'0');
	//显示日
	time_ge=time_buf1[3]%10;
	time_shi=time_buf1[3]/10;
	LCD_Show_OneChar(11,0,time_shi+'0');
	LCD_Show_OneChar(12,0,time_ge+'0');
	//显示时
	time_ge=time_buf1[4]%10;
	time_shi=time_buf1[4]/10;
	LCD_Show_OneChar(4,1,time_shi+'0');
	LCD_Show_OneChar(5,1,time_ge+'0');
	//显示分
	time_ge=time_buf1[5]%10;
	time_shi=time_buf1[5]/10;
	LCD_Show_OneChar(7,1,time_shi+'0');
	LCD_Show_OneChar(8,1,time_ge+'0');
	//显示秒
	time_ge=time_buf1[6]%10;
	time_shi=time_buf1[6]/10;
	LCD_Show_OneChar(10,1,time_shi+'0');
	LCD_Show_OneChar(11,1,time_ge+'0');
	
	//显示 : 和锁
	LCD_Show_Customer(15,0,0,close_Clock);
	LCD_Show_OneChar(6,1,':');
	LCD_Show_OneChar(9,1,':');
	//显示星期
	time_ge=time_buf1[7];
	time_ge+=(time_ge==0)?1:0;
	LCD_Show_OneChar(14,0,time_ge+'0');
}
void Show_Xin()
{
	uchar i;
	for(i=0;i<15;i+=2)
	{
		LCD_Show_Customer(i,0,0,myZi);
		LCD_Show_Customer(i+1,0,1,xin1_1);
		
		LCD_Show_Customer(i,1,1,xin1_1);
		LCD_Show_Customer(i+1,1,0,myZi);
	}
	Delay500ms();
	for(i=0;i<15;i+=2)
	{
		LCD_Show_Customer(i,0,0,myZi2);
		LCD_Show_Customer(i+1,0,1,xin1_2);
		
		LCD_Show_Customer(i,1,1,xin1_2);
		LCD_Show_Customer(i+1,1,0,myZi2);
	}
	Delay500ms();
}

LCD1602.c

#include "LCD1602.h"
void LCD_Write_Com(uchar LCD_Com)
{
	LCD_RS=0;//写命令
	LCD_RW=0;//写操作
	LCD_DATA=LCD_Com;//把数据放到数据线上
	Delay1ms(1);//延时,LCD1602准备接收数据
	LCD_EN=1;//EN拉高
	LCD_EN=0;//EN拉低
}

void LCD_Write_Data(uchar LCD_Data)
{
	LCD_RS=1;//写数据
	LCD_RW=0;//写操作
	LCD_DATA=LCD_Data;//把数据放到数据线上
	Delay1ms(1);//延时,LCD1602准备接收数据
	LCD_EN=1;//EN拉高
	LCD_EN=0;//EN拉低
}
void LCD_Init()
{
	//GPIO初始化
	P2M1&=0Xe5;P2M0&=0Xe5;//1110 0101设置为准双向口
	P0M1=0X00;P0M0=0X00;//设置为准双向口
	LCD_EN=0;
	LCD_RS=0;
	Delay5ms();
	LCD_Write_Com(0X38);//显示模式设置
	LCD_Write_Com(0X0C);//开关显示,光标设置0000 1100 D=1:开显示 C=0:不显示光标 B=0:光标不闪烁
	LCD_Write_Com(0X06);//光标设置 0000 0110 N=1 光标自动加1 S=0 整屏不移动
	LCD_Write_Com(0X01);//清屏
	Delay1ms(5);
}

void LCD_Show_OneChar(uchar X,uchar Y,uchar LCD_char)
{
	X&=0X0F;
	Y&=0X01;//限制X不能大于15,Y不能大于1
	if(Y)
	{
		X=X+0X40;//当要显示的位置在第二行时,算出地址
	}
	X=X+0X80;//计算地址指令码
	LCD_Write_Com(X);//发送命令
	LCD_Write_Data(LCD_char);//发送显示的数据
}
void LCD_Show_String(uchar X,uchar Y,uchar *LCD_String)
{
	uchar i;
	for(i=0;LCD_String[i]!='\0';i++)
	{
		LCD_Show_OneChar(X,Y,LCD_String[i]);
		X++;
	}
}
/*显示自定义字符:本函数实现在CGRAM的0X00的地址中写入自定义字符,然后显示在XY坐标位置
                  LCD1602可定义的字符可存在CGROM的0X00-0X07共8个位置
  X:列地址(0-15)
  Y:行地址(0-1)
  Num:自定义字符在CGROM中存储的位置(0-7)
  LCD_String:自定义字符的取模;若用取模软件(阴码/行列式/顺向)
*/
void LCD_Show_Customer(uchar X,uchar Y,uchar Num,uchar *LCD_Cust)//显示自定义字符
{
	uchar i;
	uchar Com=Num;//用于计算CGRAM地址指令
	X&=0X0F;
	Y&=0X01;//限制X不能大于15,Y不能大于1
	if(Y)
	{
		X=X+0X40;//当要显示的位置在第二行时,算出地址
	}
	X=X+0X80;//计算地址指令码
	Com=Com<<3;
	Com=Com+0X40;//计算指令码
	for(i=0;i<8;i++)
	{
		LCD_Write_Com(Com);//设置存入数据的地址
		Com++;
		LCD_Write_Data(LCD_Cust[i]);//逐行填充每行的内容
	}
	LCD_Write_Com(X);//发送命令
	LCD_Write_Data(Num);//发送显示的数据
}

LCD1602.h

#ifndef _LCD1602_H
#define _LCD1602_H
#define uchar unsigned char
#define uint unsigned int
#include <stc15.h>
#include "delay.h"
sbit LCD_EN=P2^1;
sbit LCD_RS=P2^4;
sbit LCD_RW=P2^3;
#define LCD_DATA P0
void LCD_Init();
void LCD_Show_OneChar(uchar X,uchar Y,uchar LCD_char);
void LCD_Show_String(uchar X,uchar Y,uchar *LCD_String);
void LCD_Show_Customer(uchar X,uchar Y,uchar Num,uchar *LCD_Cust);


#endif

iic.c

#include "iic.h"

//起始信号
void IIC_Start (void)
{
	SDA =1;
	SCL = 1;
	Delay1us();
	SDA = 0;

}

//终止信号
void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	Delay1us();
	SDA = 1;
	Delay1us();
}

//等待应答
bit IIC_WaitAck(void)
{
	bit i;
	SCL = 1;
		Delay1us();
	i = SDA;
	SCL = 0;
	return i;
}

//应答位控制
void IIC_SendAck(bit j)
{
		SCL = 0;
		Delay1us();
		SCL = 1;
		Delay1us();
		SDA = j;	
	  Delay1us();
	SCL = 0;
	SDA = 1;
		Delay1us();
}

//I2C发送1个字节数据
void IIC_SendByte(unsigned char dite)
{
	unsigned char i;
		SDA = 0;
		SCL =0;
		Delay1us();
	for(i=0;i<8;i++)
	{
		if(dite &0x80) SDA = 1;
		else SDA =0;
			Delay1us();
		dite <<=1;
		SCL = 1;
			Delay1us();
		SCL = 0;
			Delay1us();
	}
}
//I2C接收1个字节数据
unsigned char IIC_RecByte(void)
{	
		unsigned char i,tmpe; 
	
	SCL = 0;
	Delay1us();
	
		for(i=0;i<8;i++)
		{  
			SCL = 1;
			Delay1us();
					tmpe = tmpe<<1;	
			if(SDA) tmpe |=1;
			SCL =0;
		  Delay1us();
		}
	return  tmpe;	
}


 iic.h

#ifndef _IIC_H
#define _IIC_H
#include <stc15.h>
#include "delay.h"


//总线引脚定义
sbit SDA = P5^3;  /* 数据线 */
sbit SCL = P5^2;  /* 时钟线 */



void IIC_Start (void);//起始信号
void IIC_Stop(void);//终止信号
bit IIC_WaitAck(void);//等待应答
void IIC_SendAck(bit j);//应答位控制
void IIC_SendByte(unsigned char dite);//I2C发送1个字节数据
unsigned char IIC_RecByte(void);//I2C接收1个字节数据



#endif

stempmotor.c

#include "stepmotor.h"

//步进电机初始化
void StepMotor_Init()
{
	 P1M1 &= 0xF0;	P1M0 |= 0x0F;	                  //设置P1.0~P1.3为推挽输出
//	 P1M1 &= 0xF0;	P1M0 &= 0xF0;	                  //设置P1.0~P1.3为准双向
}

//电机停止
void MotorStop(void)
{
   DD=0;CC=0;BB=0;AA=0;
}


//步进电机转动:单四拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置
void Motor_Drive41(uchar X,uint Speed)
{
  if(X==1)   //顺时针转动
	{
		DD=0;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=0;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节
  }
	else       //逆时针转动
	{
		DD=1;CC=0;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节
  }	
}


//步进电机转动:双四拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置
void Motor_Drive42(uchar X,uint Speed)
{
  if(X==1)   //顺时针转动
	{
		DD=0;CC=0;BB=1;AA=1;	
    Delay1ms(Speed); //转速调节

		DD=0;CC=1;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节
  }
	else       //逆时针转动
	{
		DD=1;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=1;BB=0;AA=0;	
    Delay1ms(Speed); //转速调节

		DD=0;CC=1;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=1;	
    Delay1ms(Speed);  //转速调节
  }	
}


//步进电机转动:八拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置
void Motor_Drive8(uchar X,uint Speed)
{
  if(X==1)   //顺时针转动
	{
		DD=0;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=1;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节
		
		DD=0;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=0;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节
  }
	else       //逆时针转动
	{
		DD=1;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=0;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=1;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=1;BB=0;AA=0;	
    Delay1ms(Speed);  //转速调节
		
		DD=0;CC=1;BB=1;AA=0;	
    Delay1ms(Speed); //转速调节

		DD=0;CC=0;BB=1;AA=0;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=1;AA=1;	
    Delay1ms(Speed);  //转速调节

		DD=0;CC=0;BB=0;AA=1;	
    Delay1ms(Speed);  //转速调节
  }	
}

stempmotor.h

#ifndef _STEPMOTOR_H
#define _STEPMOTOR_H
#include <stc15.h>
#include "delay.h"

#define uchar unsigned char
#define uint unsigned int
		
sbit AA=P1^0;   //电机控制口,连接电机驱动板IN1 
sbit BB=P1^1;   //电机控制口,连接电机驱动板IN2 
sbit CC=P1^2;	//电机控制口,连接电机驱动板IN3 
sbit DD=P1^3; 	//电机控制口,连接电机驱动板IN4 


void StepMotor_Init();//步进电机初始化
void MotorStop(void);//电机停止
void Motor_Drive41(uchar X,uint Speed);//步进电机转动:单四拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置
void Motor_Drive42(uchar X,uint Speed);//步进电机转动:双四拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置
void Motor_Drive8(uchar X,uint Speed);//步进电机转动:八拍 其中X=1表示正转,X=0表示反转;Speed表示转速设置


#endif

 PCF8563.c

#include "PCF8563.h"


unsigned char time_buf1[8]={20,23,5,31,21,11,0,3};//空年月日时分秒星期(10进制)
unsigned char time_buf[8]; //空年月日时分秒星期 (16进制)

//使用封装好的I2C函数,进行函数PCF8563的写函数封装:向地址Adddrsend中写入数据Datasend
//函数编写流程为 :start->发送设备地址->等待ACK->发送需要被写的内存地址->等待ACK->发送数据写入E2PROM->等待ACK->STOP
void PCF8563_WriteOneByte(unsigned char Adddrsend, unsigned char Datasend)
{
	IIC_Start();
	IIC_SendByte(0xA2);//通过I2C总线发送数据(芯片指令)写操作
	IIC_WaitAck();
	IIC_SendByte(Adddrsend);
	IIC_WaitAck();
	IIC_SendByte(Datasend);
	IIC_WaitAck();
	IIC_Stop();
	Delay1ms(10);
}

//使用封装好的I2C函数,进行函数PCF8563的读数据函数封装:从Adddrsend中读出数据,作为返回值
//读函数编写流程:start->发送设备地址->等待ACK->发送需要被读的内存地址->等待ACK->发送读指令(设备地址)->等待ACK-->读内存数据->等待no ACK->STOP 
unsigned char PCF8563_ReadOneByte(unsigned char Adddrsend)
{
	unsigned char Rec;
	IIC_Start();
	IIC_SendByte(0xA2);//通过I2C总线发送数据(芯片指令)写操作
	IIC_WaitAck();
	IIC_SendByte(Adddrsend);
	IIC_WaitAck();
	IIC_Start();
	IIC_SendByte(0xA3);
	IIC_WaitAck();
	Rec=IIC_RecByte();
	IIC_Stop();
	return Rec;
}

/******************BCD转十进制***************************/
unsigned char bcd_dec(unsigned char bat)
{
	unsigned char temp1,temp2,tol;
	temp1=bat&0x0f;
	temp2=(bat&0xf0)>>4;
	tol=temp2*10+temp1;
	return tol; 
}
/******************十进制转BCD***************************/
unsigned char dec_bcd(unsigned char  bat)
{
	return ((bat%10) & 0x0F) | (((bat/10) << 4) & 0xF0);; 
}


//获取当前时间并转化
void get_time(void)
{
		    time_buf[6]=0x7f&PCF8563_ReadOneByte(0x02);    //读取秒
        time_buf[5]=0x7f&PCF8563_ReadOneByte(0x03);   //读取分钟
        time_buf[4]=0x3f&PCF8563_ReadOneByte(0x04);  //读取小时
        time_buf[3]=0x3f&PCF8563_ReadOneByte(0x05);   //读取天数
        time_buf[2]=0x1f&PCF8563_ReadOneByte(0x07);  //读取月
        time_buf[1]=0xff&PCF8563_ReadOneByte(0x08);    //读取年
	      time_buf[7]=0x07&PCF8563_ReadOneByte(0x06);    //读取星期
	
	
        time_buf1[6]=bcd_dec(time_buf[6]);                   //将读取的BCD码转换成十进制以便运算,秒
	      time_buf1[5]=bcd_dec(time_buf[5]);                   //将读取的BCD码转换成十进制以便运算,分
        time_buf1[4]=bcd_dec(time_buf[4]);                   //将读取的BCD码转换成十进制以便运算,小时
	      time_buf1[3]=bcd_dec(time_buf[3]);                   //将读取的BCD码转换成十进制以便运算,日
	      time_buf1[2]=bcd_dec(time_buf[2]);                   //将读取的BCD码转换成十进制以便运算,月
	      time_buf1[1]=bcd_dec(time_buf[1]);                   //将读取的BCD码转换成十进制以便运算,年
	      time_buf1[7]=bcd_dec(time_buf[7]);                   //将读取的BCD码转换成十进制以便运算,星期
		 //printf("20%d年%d月%d日%d时%d分%d秒\r\n",date.year1,date.moom1,date.dat1,date.hour1,date.min1,date.sec1);	
}


//初始化当前时间
void time_init()
{
	//将十进制数转化为BCD值,方便写入PCF8563
	time_buf[1] = dec_bcd(time_buf1[1]);
	time_buf[2] = dec_bcd(time_buf1[2]);
	time_buf[3] = dec_bcd(time_buf1[3]);
	time_buf[4] = dec_bcd(time_buf1[4]);
	time_buf[5] = dec_bcd(time_buf1[5]);
	time_buf[6] = dec_bcd(time_buf1[6]);
	time_buf[7] = dec_bcd(time_buf1[7]);

	
  PCF8563_WriteOneByte(0x02,time_buf[6]);   //写入秒     
  PCF8563_WriteOneByte(0x03,time_buf[5]);   //写入分	
	PCF8563_WriteOneByte(0x04,time_buf[4]);   //写入小时
	PCF8563_WriteOneByte(0x05,time_buf[3]);   //写入日
	PCF8563_WriteOneByte(0x07,time_buf[2]);   //写入月
	PCF8563_WriteOneByte(0x08,time_buf[1]);   //写入年
	PCF8563_WriteOneByte(0x06,time_buf[7]);   //写入星期
       
}

PCF8563.h

#ifndef _PCF8563_H
#define _PCF8563_H

#include "iic.h"
#define uchar unsigned char
#define uint unsigned int

//typedef struct {
//	uint16_t year;
//	uint8_t mon;
//	uint8_t day;
//	uint8_t hour;
//	uint8_t min;
//	uint8_t sec;
//	uint8_t week;
//}sTime;

void PCF8563_WriteOneByte(unsigned char Adddrsend, unsigned char Datasend);
unsigned char PCF8563_ReadOneByte(unsigned char Adddrsend);
unsigned char bcd_dec(unsigned char bat);
unsigned char dec_bcd(unsigned char  bat);
void time_init();//初始化当前时间
void get_time(void);//读取当前时间



#endif

Key16.c

#include "Key16.h"

uchar KeyScan_4x4(void)
{
	uchar X_temp,Y_temp,temp;
	X_temp=0XF0;//列值赋初值
	Y_temp=0X0F;//行值赋初值
	P2M1&=0X3F;P2M0|=0XC0;//设置P2.6-P2.7为强推挽输出 0011 1111;1100 0000
	P4M1&=0X0F;P4M0|=0XF0;//设置P4.4-P4.7为强推挽输出 0000 1111;1111 0000
	P5M1&=0XF3;P5M0|=0X0C;//设置P5.2-P5.3为强推挽输出 1111 0011;0000 1100
	
	ROW1=1;ROW2=1;ROW3=1;ROW4=1;//行置高
	COL1=0;COL2=0;COL3=0;COL4=0;//列置低
	//所用到行IO口配置为输入,进行检测
	Delay1ms(10);
	P4M1&=0X0F;P4M0&=0X0F;//设置P4.4-P4.7为准双向口
	Delay1ms(10);
	if(ROW1==0)//检测行1电平是否为低电平
	{
		Delay1ms(10);
		if(ROW1==0)
		Y_temp&=0X0E;
	}
	if(ROW2==0)//检测行2电平是否为低电平
	{
		Delay1ms(10);
		if(ROW2==0)
		Y_temp&=0X0D;
	}
	if(ROW3==0)//检测行3电平是否为低电平
	{
		Delay1ms(10);
		if(ROW3==0)
		Y_temp&=0X0B;
	}
	if(ROW4==0)//检测行4电平是否为低电平
	{
		Delay1ms(10);
		if(ROW4==0)
		Y_temp&=0X07;
	}
	P2M1&=0X3F;P2M0|=0XC0;//设置P2.6-P2.7为强推挽输出 0011 1111;1100 0000
	P4M1&=0X0F;P4M0|=0XF0;//设置P4.4-P4.7为强推挽输出 0000 1111;1111 0000
	P5M1&=0XF3;P5M0|=0X0C;//设置P5.2-P5.3为强推挽输出 1111 0011;0000 1100
	ROW1=0;ROW2=0;ROW3=0;ROW4=0;//行置低
	COL1=1;COL2=1;COL3=1;COL4=1;//列置高
	Delay1ms(10);
	P2M1&=0X3F;P2M0&=0X3F;//设置P2.6-P2.7为准双向口
	P5M1&=0XF3;P5M0&=0XF3;//设置P5.2-P5.3为准双向口
	Delay1ms(10);
	if(COL1==0)//检测列1电平是否为低电平
	{
		Delay1ms(10);
		if(COL1==0)
		X_temp&=0XE0;
	}
	if(COL2==0)//检测列2电平是否为低电平
	{
		Delay1ms(10);
		if(COL2==0)
		X_temp&=0XD0;
	}
	if(COL3==0)//检测列3电平是否为低电平
	{
		Delay1ms(10);
		if(COL3==0)
		X_temp&=0XB0;
	}
	if(COL4==0)//检测列4电平是否为低电平
	{
		Delay1ms(10);
		if(COL4==0)
		X_temp&=0X70;
	}
	//将行值和列值合并,得到按键对应的编码值,该值与16个按键一一对应
	temp=X_temp|Y_temp;
	temp=~temp;
	//将按键检测的原始编码值解析对应按键值信息
	switch(temp)//颠倒键值
	{
		case 0X11:return '/';//1
		case 0X21:return 'x';//2
		case 0X41:return '-';//3
		case 0X81:return '+';//4
		case 0X12:return '=';//5
		case 0X22:return '9';//6
		case 0X42:return '8';//7
		case 0X82:return '7';//8
		case 0X14:return 'C';//9
		case 0X24:return '6';//0
		case 0X44:return '5';//a
		case 0X84:return '4';//b
		case 0X18:return '<';//c
		case 0X28:return '3';//d
		case 0X48:return '2';//e
		case 0X88:return '1';//f
		default:return 0;
	}
}

Key16.h

#ifndef _KEY_4X4_H
#define _KEY_4X4_H

#include <stc15.h>
#include "delay.h"

#define uchar unsigned char
#define uint unsigned int
 
/*
矩阵按键引脚定义*/
sbit COL4=P5^2;    //4*4矩阵检测列检测端口
sbit COL3=P5^3;    //4*4矩阵检测列检测端口
sbit COL2=P2^6;    //4*4矩阵检测列检测端口
sbit COL1=P2^7;    //4*4矩阵检测列检测端口 
sbit ROW4=P4^4;    //4*4矩阵检测行检测端口
sbit ROW3=P4^5;    //4*4矩阵检测行检测端口
sbit ROW2=P4^6;    //4*4矩阵检测行检测端口
sbit ROW1=P4^7;    //4*4矩阵检测行检测端口


uchar KeyScan_4x4(void);

#endif

zimo.h

#ifndef _ZIMO_H
#define _ZIMO_H
#define uchar unsigned char
#define uint unsigned int

uchar code close_Clock[]={0x0E,0x0A,0x0A,0x0A,0x1F,0x11,0x11,0x1F};//??
uchar code guan[] = {0x11,0x0A,0x1F,0x0A,0x1F,0x0A,0x1B,0x00};
uchar code kai[] = {0x1F,0x0A,0x0A,0x1F,0x0A,0x0A,0x0A,0x00};
uchar code open_Clock[]={0x0E,0x02,0x02,0x02,0x1F,0x11,0x11,0x1F};//???
uchar code myZi[] = {0x00,0x00,0x0A,0x15,0x11,0x0A,0x04,0x00};
uchar code myZi2[] = {0x00,0x0A,0x15,0x15,0x11,0x0A,0x04,0x00};
uchar code xin1_2[] = {0x00,0x0A,0x1F,0x1F,0x1F,0x0E,0x04,0x00};
uchar code xin1_1[] = {0x00,0x00,0x0A,0x1F,0x1F,0x0E,0x04,0x00};


#endif

  • 22
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值