HYM8563T时钟芯片---软件模拟iic

HYM8563T芯片与PCF8563时钟芯片各种参数是一样的

市面上PCF8563的资料代码还是挺多的!

直接上代码:

软件模拟iIC

/******************************************************************************
* @ File name --> iic.c
* @ Author    --> By@ shun
* @ Version   --> V1.0
* @ Date      --> 07 - 10 - 2012
* @ Brief     --> MCU模拟IIC通讯函数
* @           --> 要改变传输频率,请修改延时函数中的数值即可
*
* @ Copyright (C) 20**
* @ All rights reserved
*******************************************************************************
*                                  File Update
* @ Version   --> V1.1.1
* @ Author    --> By@ shun
* @ Date      --> 12 - 10 - 2013
* @ Revise    --> 增加是否使用延时函数调整通讯频率宏定义 
*
* @ Version   --> V1.1.2
* @ Author    --> By@ shun
* @ Date      --> 05 - 01 - 2014
* @ Revise    --> 简化代码量和优化风格,简化初始化控制端口代码,尽量在头文件中修改宏定义,方便移植
*
******************************************************************************/

#include "iic.h"
#include "Delay.h"
/******************************************************************************
* Function Name --> IIC_GPIO_Init
* Description   --> GPIO初始化
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_GPIO_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(IIC_SCL_PORT_RCC|IIC_SDA_PORT_RCC,ENABLE);
    
	GPIO_InitStructure.GPIO_Pin=IIC_SCL_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_Init(IIC_SCL_PORT,&GPIO_InitStructure);
    
    GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);

	IIC_SDA_HIGH();  //置IIC总线空闲
	IIC_SCL_HIGH();
}

/******************************************************************************
* Function Name --> SDA_OUT
* Description   --> SDA输出配置	
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_SDA_OUT(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
	GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}

/******************************************************************************
* Function Name --> SDA_IN
* Description   --> SDA输入配置
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_SDA_IN(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}

/******************************************************************************
* Function Name --> IIC启动
* Description   --> SCL高电平期间,SDA由高电平突变到低电平时启动总线
*                   SCL: __________
*                                  \__________
*                   SDA: _____
*                             \_______________
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_Start(void)
{
	IIC_SDA_OUT();	//设置成输出

	IIC_SCL_HIGH();	//为SDA下降启动做准备
	IIC_SDA_HIGH();	//在SCL高电平时,SDA为下降沿时候总线启动
	
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */
	
	IIC_Delay();
	IIC_SDA_LOW();	//突变,总线启动
	IIC_Delay();
	IIC_SCL_LOW();
	IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */
	
	IIC_SDA = 0;	//突变,总线启动
	IIC_SCL = 0;

#endif  /* end __USER_DELAY_CLK */
}

/******************************************************************************
* Function Name --> IIC停止
* Description   --> SCL高电平期间,SDA由低电平突变到高电平时停止总线
*                   SCL: ____________________
*                                  __________
*                   SDA: _________/
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_Stop(void)
{
	IIC_SDA_OUT();	//设置成输出

	IIC_SDA_LOW();	//为SDA上升做准备
	
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

	IIC_Delay();
	IIC_SCL_HIGH();	//在SCL高电平时,SDA为上升沿时候总线停止
	IIC_Delay();
	IIC_SDA_HIGH();	//突变,总线停止
	IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

	IIC_SCL = 1;	//在SCL高电平时,SDA为上升沿时候总线停止
	IIC_SDA = 1;	//突变,总线停止

#endif  /* end __USER_DELAY_CLK */
}

/******************************************************************************
* Function Name --> 主机向从机发送应答信号
* Description   --> none
* Input         --> a:应答信号
*                      0:应答信号
*                      1:非应答信号
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void IIC_Ack(u8 a)
{
	IIC_SDA_OUT();	//设置成输出

	if(a)	IIC_SDA_HIGH();	//放上应答信号电平
	else	IIC_SDA_LOW();
	
#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

	IIC_Delay();
	IIC_SCL_HIGH();	//为SCL下降做准备
	IIC_Delay();
	IIC_SCL_LOW();	//突变,将应答信号发送过去
	IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

	IIC_SCL = 1;	//为SCL下降做准备
	IIC_SCL = 0;	//突变,将应答信号发送过去

#endif  /* end __USER_DELAY_CLK */
}

/******************************************************************************
* Function Name --> 向IIC总线发送一个字节数据
* Description   --> none
* Input         --> dat:要发送的数据
* Output        --> none
* Reaturn       --> ack:返回应答信号
******************************************************************************/
u8 IIC_Write_Byte(u8 dat)
{
	u8 i;
	u8 iic_ack=0;	//iic应答标志

	IIC_SDA_OUT();	//设置成输出

	for(i = 0;i < 8;i++)
	{
		if(dat & 0x80)	IIC_SDA_HIGH();	//判断发送位,先发送高位
		else	IIC_SDA_LOW();

#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */
			
		IIC_Delay();
		IIC_SCL_HIGH();	//为SCL下降做准备
		IIC_Delay();
		IIC_SCL_LOW();	//突变,将数据位发送过去
		dat<<=1;	//数据左移一位
	}	//字节发送完成,开始接收应答信号

	IIC_SDA_HIGH();	//释放数据线

	IIC_SDA_IN();	//设置成输入

	IIC_Delay();
	IIC_SCL_HIGH();	//为SCL下降做准备
	IIC_Delay();

#else  /* 否则不使用延时函数改变通讯频率 */

		IIC_SCL = 1;	//为SCL下降做准备
		IIC_SCL = 0;	//突变,将数据位发送过去
		dat<<=1;	//数据左移一位
	}	//字节发送完成,开始接收应答信号

	IIC_SDA = 1;	//释放数据线

	IIC_SDA_IN();	//设置成输入

	IIC_SCL = 1;	//为SCL下降做准备

#endif  /* end __USER_DELAY_CLK */
	
	iic_ack |= IN_SDA;	//读入应答位
	IIC_SCL_LOW();
	return iic_ack;	//返回应答信号
}

/******************************************************************************
* Function Name --> 从IIC总线上读取一个字节数据
* Description   --> none
* Input         --> none
* Output        --> none
* Reaturn       --> x:读取到的数据
******************************************************************************/
u8 IIC_Read_Byte(void)
{
	u8 i;
	u8 x=0;

	IIC_SDA_HIGH();	//首先置数据线为高电平

	IIC_SDA_IN();	//设置成输入

	for(i = 0;i < 8;i++)
	{
		x <<= 1;	//读入数据,高位在前

#if _USER_DELAY_CLK==1  /* 定义了则使用延时函数来改变通讯频率 */

		IIC_Delay();
		IIC_SCL_HIGH();	//突变
		IIC_Delay();
		
		if(IN_SDA)	x |= 0x01;	//收到高电平

		IIC_SCL_LOW();
		IIC_Delay();
	}	//数据接收完成

#else  /* 否则不使用延时函数改变通讯频率 */

		IIC_SCL = 1;	//突变
		
		if(IN_SDA)	x |= 0x01;	//收到高电平

		IIC_SCL = 0;
	}	//数据接收完成

#endif  /* end __USER_DELAY_CLK */

	IIC_SCL_LOW();

	return x;	//返回读取到的数据
}





iic.h

/******************************************************************************
* @ File name --> iic.h
* @ Author    --> By@ shun
* @ Version   --> V1.0
* @ Date      --> 07 - 10 - 2012
* @ Brief     --> MCU模拟IIC通讯函数
* @           --> 要改变传输频率,请修改延时函数中的数值即可
******************************************************************************/

#ifndef _iic_h_ 
#define _iic_h_

/******************************************************************************
                                 外部函数头文件                        
******************************************************************************/
#include "stm32f10x.h"   


/******************************************************************************
                                 外部引脚修改区                        
******************************************************************************/
/*  IIC_SCL时钟端口、引脚定义 */
#define IIC_SCL_PORT 			GPIOC   
#define IIC_SCL_PIN 			(GPIO_Pin_11)
#define IIC_SCL_PORT_RCC		RCC_APB2Periph_GPIOC

/*  IIC_SDA时钟端口、引脚定义 */
#define IIC_SDA_PORT 			GPIOC  
#define IIC_SDA_PIN 			(GPIO_Pin_10)
#define IIC_SDA_PORT_RCC		RCC_APB2Periph_GPIOC


/******************************************************************************
                             对于低速晶振的支持
                     是否使用延时函数进行调整通讯频率
******************************************************************************/

#define _USER_DELAY_CLK					1	//定义了则使用延时调整通讯频率
											//0:不使用延时函数调整通讯频率,对于低速MCU时候用
											//1:使用延时函数调整通讯频率,对于高速MCU时候用

/******************************************************************************
                                位带操作
******************************************************************************/
//#define IIC_SCL					PBout(6)
//#define IIC_SDA					PBout(7)	//IIC发送数据用
//#define IN_SDA					PBin(7)	    //IIC读取数据用

#define IIC_SDA_HIGH() 			GPIO_SetBits(IIC_SDA_PORT,IIC_SDA_PIN)		//SDA置位
#define IIC_SDA_LOW() 			GPIO_ResetBits(IIC_SDA_PORT,IIC_SDA_PIN)		//SDA清0

#define IIC_SCL_HIGH() 			GPIO_SetBits(IIC_SCL_PORT,IIC_SCL_PIN)		//SCL置位
#define IIC_SCL_LOW() 			GPIO_ResetBits(IIC_SCL_PORT,IIC_SCL_PIN)		//SCL清0

#define IN_SDA                  GPIO_ReadInputDataBit(IIC_SDA_PORT, IIC_SDA_PIN)

/******************************************************************************
                               通讯频率延时函数
                    需要调整通讯频率的请修改此函数值即可
******************************************************************************/

#if	_USER_DELAY_CLK==1	//定义了则使用

	#define IIC_Delay()                 Delay_us(2) //要改变请修改delay_us()中的数值即可

#endif

/******************************************************************************
                                 外部功能函数
******************************************************************************/

void IIC_GPIO_Init(void);	    //GPIO初始化

void IIC_Start(void);	        //IIC启动

void IIC_Stop(void);	        //IIC停止

void IIC_Ack(u8 a);	            //主机向从机发送应答信号

u8 IIC_Write_Byte(u8 dat);	    //向IIC总线发送一个字节数据

u8 IIC_Read_Byte(void);	        //从IIC总线上读取一个字节数据



#endif  /* end iic.h */




HYM8563

/**
  *****************************************************************************
  *                            时钟芯片PCF8563驱动
  * @File    : pcf8563.c
  * @By      : shun
  * @Version : V1.0
  * @Date    : 2018 / 12 / 13
  *
  *****************************************************************************
**/


#include "pcf8563.h"


/******************************************************************************
                            定义相关的变量函数
******************************************************************************/

unsigned char buffer[4];   //年月日周
unsigned char buffer1[4];  //时分秒

/**
  *****************************************************************************
  * @Name   : 将BIN(十进制)转换为BCD
  *
  * @Brief  : none
  *
  * @Input  : BINValue: 输入BIN
  *
  * @Output : none
  *
  * @Return : BCD格式数值
  *****************************************************************************
**/
static unsigned char RTC_BinToBcd2(unsigned char BINValue)
{
	unsigned char bcdhigh = 0;
	
	while (BINValue >= 10)
	{
		bcdhigh++;
		BINValue -= 10;
	}
    
	return ((unsigned char)(bcdhigh << 4) | BINValue);
}

/**
  *****************************************************************************
  * @Name   : 将BCD转换为BIN
  *
  * @Brief  : none
  *
  * @Input  : BCDValue: 输入BCD
  *
  * @Output : none
  *
  * @Return : BIN格式数值
  *****************************************************************************
**/
static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
{
	unsigned char tmp = 0;
	
	tmp = ((unsigned char)(BCDValue & (unsigned char)0xF0) >> (unsigned char)0x04) * 10;
	return (tmp + (BCDValue & (unsigned char)0x0F));
}

/*
static unsigned char RTC_Bcd2ToBin(unsigned char BCDValue)
{
	unsigned char tmp = 0;
	
	tmp = (BCDValue >> 4) * 10; // 提取十位部分并转换为十进制
	return (tmp + (BCDValue & 0x0F)); // 加上个位部分
}
*/

/******************************************************************************
  * @Name   : PCF8563某寄存器写入一个字节数据
  *
  * @Brief  : none
  *
  * @Input  : REG_ADD:要操作寄存器地址
  *           dat:    要写入的数据
  *
  * @Output : none
  *
  * @Return : none
**/
void PCF8563_Write_Byte(unsigned char REG_ADD, unsigned char dat)
{
	IIC_Start();                          //启动IIC
	if(!(IIC_Write_Byte(PCF8563_Write)))  //发送写命令并检查应答位
	{
		IIC_Write_Byte(REG_ADD);          //写入地址
		IIC_Write_Byte(dat);              //发送数据
	}
	IIC_Stop();                           //关闭IIC
} 

/******************************************************************************
  * @Name   : PCF8563某寄存器读取一个字节数据
  *
  * @Brief  : none
  *
  * @Input  : REG_ADD:要操作寄存器地址
  *
  * @Output : none
  *
  * @Return : 读取得到的寄存器的值
  *****************************************************************************
**/
unsigned char PCF8563_Read_Byte(unsigned char REG_ADD)
{
	unsigned char ReData;                 //定义变量接收数据
	
	IIC_Start();                          //启动IIC
	if(!(IIC_Write_Byte(PCF8563_Write)))  //发送写命令并检查应答位
	{
		IIC_Write_Byte(REG_ADD);          //确定要操作的寄存器
		IIC_Start();                      //重启总线
		IIC_Write_Byte(PCF8563_Read);     //发送读取命令
		ReData = IIC_Read_Byte( );        //读取数据
		IIC_Ack(1);                       //发送非应答信号结束数据传送
	}
	IIC_Stop();                           //关闭IIC
	return ReData;
}

/******************************************************************************
  * @Name   : PCF8563写入多组数据
  *
  * @Brief  : none
  *
  * @Input  : REG_ADD:要操作寄存器起始地址
  *           num:    写入数据数量
  *           *WBuff: 写入数据缓存
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_Write_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
{
	unsigned char i = 0;                  //定义i辅助循环发送
		 	
	IIC_Start();                          //启动IIC
	if(!(IIC_Write_Byte(PCF8563_Write)))  //发送写命令并检查应答位
	{
		IIC_Write_Byte(REG_ADD);          //定位起始寄存器地址
		for(i = 0;i < num;i++)            //循环num次,达到多个数据写入
		{
			IIC_Write_Byte(*pBuff);       //写入数据
			pBuff++;                      //数据缓存地址增加
		}
	}
	IIC_Stop();                           //关闭IIC
}

/******************************************************************************
  * @Name   : PCF8563读取多组数据
  *
  * @Brief  : none
  *
  * @Input  : REG_ADD:要操作寄存器起始地址
  *           num:    读取数据数量
  *
  * @Output : *WBuff: 读取数据缓存
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_Read_nByte(unsigned char REG_ADD, unsigned char num, unsigned char *pBuff)
{
	unsigned char i = 0;                  //定义变量i辅助多次读取
	
	IIC_Start();                          //启动IIC
	if(!(IIC_Write_Byte(PCF8563_Write)))  //发送写命令并检查应答位
	{
		IIC_Write_Byte(REG_ADD);          //定位起始寄存器地址
		IIC_Start();                      //重启总线
		IIC_Write_Byte(PCF8563_Read);     //发送读取命令
		for(i = 0;i < num;i++)            //循环num次完成多次读取
		{
			*pBuff = IIC_Read_Byte();     //读取数据
			if(i == (num - 1)) IIC_Ack(1);//发送非应答信号,知道完成数据量
			else IIC_Ack(0);              //发送应答信号
			pBuff++;                      //读取缓冲区地址增加
		}
	}
	IIC_Stop();	                          //关闭IIC
}

/******************************************************************************
  * @Name   : PCF8563检测是否存在
  *
  * @Brief  : 向定时器倒计时寄存器写入一个数值再读取出来做对比,相同正确,不同则错误
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : 0: 正常
  *           1: PCF8563错误或者损坏
  *****************************************************************************
**/
unsigned char PCF8563_Check(void)
{
	unsigned char test_value = 0;
	unsigned char Time_Count = 0;          //定时器倒计时数据缓存

	if(PCF8563_Read_Byte(PCF8563_Address_Timer) & 0x80)             //如果打开了定时器,则先关闭
	{
		PCF8563_Write_Byte(PCF8563_Address_Timer, PCF_Timer_Close); //先关闭定时器
		Time_Count = PCF8563_Read_Byte(PCF8563_Address_Timer_VAL);  //先保存计数值
	}

	PCF8563_Write_Byte(PCF8563_Address_Timer_VAL, PCF8563_Check_Data);  //写入检测值
	for(test_value = 0;test_value < 50;test_value++)  {}  //延时一定时间再读取
	test_value = PCF8563_Read_Byte(PCF8563_Address_Timer_VAL);  //再读取回来

	if(Time_Count != 0)  //启动了定时器功能,则恢复
	{
		PCF8563_Write_Byte(PCF8563_Address_Timer_VAL, Time_Count);  //恢复现场
		PCF8563_Write_Byte(PCF8563_Address_Timer, PCF_Timer_Open);  //启动定时器
	}

	if(test_value != PCF8563_Check_Data)  return 1;  //器件错误或者损坏
	
	return 0;  //正常
}

/**
  *****************************************************************************
  * @Name   : PCF8563启动
  *
  * @Brief  : none
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_Start(void)
{
	unsigned char temp = 0;
	
	temp = PCF8563_Read_Byte(PCF8563_Address_Control_Status_1);  //读取控制/状态寄存器1
	if (temp & PCF_Control_ChipStop)
	{
		temp &= PCF_Control_ChipRuns;  //运行芯片
	}
	if ((temp & (1<<7)) == 0)  //普通模式
	{
		temp &= PCF_Control_TestcClose;  //电源复位模式失效
	}
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_1, temp);  //再写入数值
}

/**
  *****************************************************************************
  * @Name   : PCF8563停止
  *
  * @Brief  : 时钟频率输出CLKOUT 在 32.768kHz 时可用
  *
  * @Input  : none
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_Stop(void)
{
	unsigned char temp = 0;
	
	temp = PCF8563_Read_Byte(PCF8563_Address_Control_Status_1);  //读取控制/状态寄存器1
	temp |= PCF_Control_ChipStop;  //停止运行
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_1, temp);  //再写入数值
}

/**
  *****************************************************************************
  * @Name   : PCF8563设置运行模式
  *
  * @Brief  : none
  *
  * @Input  : Mode: 运行模式
  *                 = PCF_Mode_Normal
  *                 = PCF_Mode_EXT_CLK
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetMode(unsigned char Mode)
{
	unsigned char temp = 0;
	
	temp = PCF8563_Read_Byte(PCF8563_Address_Control_Status_1);  //读取寄存器值
	if (Mode == PCF_Mode_EXT_CLK)  //EXT_CLK测试模式
	{
		temp |= PCF_Control_Status_EXT_CLKMode;
	}
	else if (Mode == PCF_Mode_Normal)
	{
		temp &= PCF_Control_Status_NormalMode;
		temp &= ~(1<<3);  //电源复位功能失效
	}
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_1, temp);
}

/**
  *****************************************************************************
  * @Name   : PCF8563设置电源复位功能开启与关闭
  *
  * @Brief  : none
  *
  * @Input  : NewState: 状态,PCF8563_PowerResetEnablePCF8563_PowerResetDisable
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetPowerReset(unsigned char NewState)
{
	unsigned char TestC = 0;
	
	TestC = PCF8563_Read_Byte(PCF8563_Address_Control_Status_1);  //获取寄存器值
	TestC &= ~(1<<3);  //清除之前设置
	if (NewState == PCF8563_PowerResetEnable)  //复位功能有效
	{
		TestC |= PCF8563_PowerResetEnable;
	}
	else if (NewState == PCF8563_PowerResetDisable)
	{
		TestC &= ~PCF8563_PowerResetEnable;  //失效,普通模式是值逻辑0,即失效
	}
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_1, TestC);  //写入数值
}

/**
  *****************************************************************************
  * @Name   : PCF8563设置输出频率
  *
  * @Brief  : none
  *
  * @Input  :*PCF_CLKOUTStruct: 频率结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetCLKOUT(_PCF8563_CLKOUT_Typedef* PCF_CLKOUTStruct)
{
	unsigned char tmp = 0;
	
	tmp = PCF8563_Read_Byte(PCF8563_Address_CLKOUT);  //读取寄存器值
	tmp &= 0x7c;  //清除之前设置
	if (PCF_CLKOUTStruct->CLKOUT_NewState == PCF_CLKOUT_Open)
	{
		tmp |= PCF_CLKOUT_Open;
	}
	else
	{
		tmp &= PCF_CLKOUT_Close;
	}
	tmp |= PCF_CLKOUTStruct->CLKOUT_Frequency;
	
	PCF8563_Write_Byte(PCF8563_Address_CLKOUT, tmp);
}

/**
  *****************************************************************************
  * @Name   : PCF8563设置定时器
  *
  * @Brief  : none
  *
  * @Input  :*PCF_TimerStruct: 定时器结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetTimer(_PCF8563_Timer_Typedef* PCF_TimerStruct)
{
	unsigned char Timer_Ctrl = 0;
	unsigned char Timer_Value = 0;
	
	Timer_Ctrl = PCF8563_Read_Byte(PCF8563_Address_Timer);  //获的控制寄存器值
	Timer_Value = PCF8563_Read_Byte(PCF8563_Address_Timer_VAL);  //获取倒计时数值
	//
	//先停止定时器
	//
	Timer_Ctrl &= PCF_Timer_Close;
	PCF8563_Write_Byte(PCF8563_Address_Timer, Timer_Ctrl);
	
	Timer_Ctrl &= 0x7c;  //清除定时器之前设置
	
	if (PCF_TimerStruct->RTC_Timer_NewState == PCF_Timer_Open)  //开启
	{
		Timer_Ctrl |= PCF_Timer_Open;
		Timer_Ctrl |= PCF_TimerStruct->RTC_Timer_Frequency;  //填上新的工作频率
		if (PCF_TimerStruct->RTC_Timer_Value)  //需要填上新的计数值
		{
			Timer_Value = PCF_TimerStruct->RTC_Timer_Value;  //填上新的计数值
		}
	}
	else
	{
		Timer_Ctrl &= PCF_Timer_Close;
	}
	PCF8563_Write_Byte(PCF8563_Address_Timer_VAL, Timer_Value);  //写入倒计时数值
	
	if (PCF_TimerStruct->RTC_Timer_Interrupt == PCF_Time_INT_Open)  //开启了中断输出
	{
		Timer_Value = PCF8563_Read_Byte(PCF8563_Address_Control_Status_2);  //获取控制/状态寄存器2数值
		Timer_Value &= PCF_Time_INT_Close;  //清除定时器中断使能
		Timer_Value &= ~(1<<2);  //清除定时器中断标志
		Timer_Value &= ~(1<<4);  //当 TF 有效时 INT 有效 (取决于 TIE 的状态) 
		Timer_Value |= PCF_Time_INT_Open;  //开启定时器中断输出
		PCF8563_Write_Byte(PCF8563_Address_Control_Status_2, Timer_Value);
	}
	else
	{
		Timer_Value = PCF8563_Read_Byte(PCF8563_Address_Control_Status_2);  //获取控制/状态寄存器2数值
		Timer_Value &= PCF_Time_INT_Close;  //清除定时器中断使能
		Timer_Value |= PCF_Time_INT_Open;  //开启定时器中断输出
		PCF8563_Write_Byte(PCF8563_Address_Control_Status_2, Timer_Value);
	}
	
	PCF8563_Write_Byte(PCF8563_Address_Timer, Timer_Ctrl);  //设置定时器控制寄存器
}

/**
  *****************************************************************************
  * @Name   : 设置时间,主要用于后台调用,或者初始化时间用
  *
  * @Brief  : 秒默认就设置成0x00了,形参里面不体现,星期值范围:0 ~ 6
  *
  * @Input  : PCF_Format:  数据格式
  *                        = PCF_Format_BIN
  *                        = PCF_Format_BCD
  *           PCF_Century: 世纪位设定
  *                        = PCF_Century_19xx
  *                        = PCF_Century_20xx
  *           Year:        年
  *           Month:       月
  *           Date:        日
  *           Week:        星期
  *           Hour:        时
  *           Minute:      分
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_Set_Times(unsigned char PCF_Format,\
                       unsigned char PCF_Century,\
	                   unsigned char Year, unsigned char Month, unsigned char Date, unsigned char Week,\
                       unsigned char Hour, unsigned char Minute)
{
	_PCF8563_Time_Typedef Time_InitStructure;
	_PCF8563_Date_Typedef Date_InitStructure;
	
	if (PCF_Format == PCF_Format_BIN)
	{
		//
		//判断数据是否符合范围
		//
		if (Year > 99)   Year  = 0;  //恢复00年
		if (Month > 12)  Month = 1;  //恢复1月
		if (Date > 31)   Date  = 1;  //恢复1日
		if (Week > 6)    Week  = 1;  //恢复星期一
		
		if (Hour > 23)    Hour   = 0;  //恢复0小时
		if (Minute > 59)  Minute = 0;  //恢复0分钟
		
		//
		//转换一下
		//
		Date_InitStructure.RTC_Years    = RTC_BinToBcd2(Year);
		Date_InitStructure.RTC_Months   = RTC_BinToBcd2(Month);
		Date_InitStructure.RTC_Days     = RTC_BinToBcd2(Date);
		Date_InitStructure.RTC_WeekDays = RTC_BinToBcd2(Week);
		
		Time_InitStructure.RTC_Hours    = RTC_BinToBcd2(Hour);
		Time_InitStructure.RTC_Minutes  = RTC_BinToBcd2(Minute);
	}
	Time_InitStructure.RTC_Seconds = 0x00;  //恢复0秒
	Time_InitStructure.RTC_Seconds &= PCF_Accuracy_ClockYes;  //保证准确的时间
	//
	//判断世纪位
	//
	if (PCF_Century == PCF_Century_19xx)
	{
		Date_InitStructure.RTC_Months |= PCF_Century_SetBitC;
	}
	else
	{
		Date_InitStructure.RTC_Months &= ~PCF_Century_SetBitC;
	}
	//
	//写入信息到寄存器
	//
	buffer[0] = Time_InitStructure.RTC_Seconds;
	buffer[1] = Time_InitStructure.RTC_Minutes;
	buffer[2] = Time_InitStructure.RTC_Hours;
	PCF8563_Write_nByte(PCF8563_Address_Seconds, 3, buffer);  //写入时间信息
	
	buffer[0] = Date_InitStructure.RTC_Days;
	buffer[1] = Date_InitStructure.RTC_WeekDays;
	buffer[2] = Date_InitStructure.RTC_Months;
	buffer[3] = Date_InitStructure.RTC_Years;
	PCF8563_Write_nByte(PCF8563_Address_Days,    4, buffer);  //写入日期信息
}

/**
   ============================================================================
                     #### 所有寄存器全部操作功能函数 ####
   ============================================================================
**/

/**
  *****************************************************************************
  * @Name   : 判断时间信息是否符合范围,超出将恢复初值
  *
  * @Brief  : 星期值范围:0 ~ 6
  *
  * @Input  : PCF_DataStruct: 寄存器结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
static void IS_PCF8563_Data(_PCF8563_Register_Typedef* PCF_DataStruct)
{
	if (PCF_DataStruct->Years > 99)           PCF_DataStruct->Years          = 0;  //恢复00年
	if (PCF_DataStruct->Months_Century > 12)  PCF_DataStruct->Months_Century = 1;  //恢复1月
	if (PCF_DataStruct->Days > 31)            PCF_DataStruct->Days           = 1;  //恢复1日
	if (PCF_DataStruct->WeekDays > 6)         PCF_DataStruct->WeekDays       = 1;  //恢复星期一
	
	if (PCF_DataStruct->Hours > 23)           PCF_DataStruct->Hours          = 0;  //恢复0小时
	if (PCF_DataStruct->Minutes > 59)         PCF_DataStruct->Minutes        = 0;  //恢复0分钟
	if (PCF_DataStruct->Seconds > 59)         PCF_DataStruct->Seconds        = 0;  //恢复0秒
}

/**
  *****************************************************************************
  * @Name   : PCF8563写入寄存器
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *           PCF_Century:    世纪位设定
  *                           = PCF_Century_19xx
  *                           = PCF_Century_20xx
  *           PCF_DataStruct: 寄存器结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetRegister(unsigned char PCF_Format, unsigned char PCF_Century, _PCF8563_Register_Typedef* PCF_DataStruct)
{
	if (PCF_Format == PCF_Format_BIN)  //十进制格式,需要转换一下
	{
		//
		//判断数值是否在范围之内
		//
		IS_PCF8563_Data(PCF_DataStruct);
		//
		//需要转换一下
		//
		PCF_DataStruct->Years          = RTC_BinToBcd2(PCF_DataStruct->Years);
		PCF_DataStruct->Months_Century = RTC_BinToBcd2(PCF_DataStruct->Months_Century);
		PCF_DataStruct->Days           = RTC_BinToBcd2(PCF_DataStruct->Days);
		PCF_DataStruct->WeekDays       = RTC_BinToBcd2(PCF_DataStruct->WeekDays);
		
		PCF_DataStruct->Hours          = RTC_BinToBcd2(PCF_DataStruct->Hours);
		PCF_DataStruct->Minutes        = RTC_BinToBcd2(PCF_DataStruct->Minutes);
		PCF_DataStruct->Seconds        = RTC_BinToBcd2(PCF_DataStruct->Seconds);
		
		PCF_DataStruct->Day_Alarm      = RTC_BinToBcd2(PCF_DataStruct->Day_Alarm);
		PCF_DataStruct->WeekDays_Alarm = RTC_BinToBcd2(PCF_DataStruct->WeekDays_Alarm);
		
		PCF_DataStruct->Hour_Alarm     = RTC_BinToBcd2(PCF_DataStruct->Hour_Alarm);
		PCF_DataStruct->Minute_Alarm   = RTC_BinToBcd2(PCF_DataStruct->Minute_Alarm);
	}
	//
	//判断世纪位
	//
	if (PCF_Century == PCF_Century_19xx)
	{
		PCF_DataStruct->Months_Century |= PCF_Century_SetBitC;
	}
	else
	{
		PCF_DataStruct->Months_Century &= ~PCF_Century_SetBitC;
	}
	//
	//关闭所有闹铃,中断输出
	//
	PCF_DataStruct->Timer_Control    &= ~(1<<7);
	PCF_DataStruct->CLKOUT_Frequency &= ~(1<<7);
	PCF_DataStruct->WeekDays_Alarm   &= ~(1<<7);
	PCF_DataStruct->Day_Alarm        &= ~(1<<7);
	PCF_DataStruct->Hour_Alarm       &= ~(1<<7);
	PCF_DataStruct->Minute_Alarm     &= ~(1<<7);
	PCF_DataStruct->Control_Status_2 &= ~(3<<0);
	//
	//写入数据到寄存器
	//
	PCF8563_Write_nByte(PCF8563_Address_Control_Status_1, 16, (unsigned char*)PCF_DataStruct);
}

/**
  *****************************************************************************
  * @Name   : PCF8563读取寄存器
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *
  * @Output : *PCF_Century:   世纪位,0:21世纪;1:20世纪
  *           PCF_DataStruct: 寄存器结构指针
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_GetRegister(unsigned char PCF_Format, unsigned char *PCF_Century, _PCF8563_Register_Typedef* PCF_DataStruct)
{
	//
	//读取全部寄存器数值
	//
	PCF8563_Read_nByte(PCF8563_Address_Control_Status_1, 16, (unsigned char*)PCF_DataStruct);
	//
	//判断世纪位数值
	//
	if (PCF_DataStruct->Months_Century & PCF_Century_SetBitC)
	{
		*PCF_Century = 1;
	}
	else
	{
		*PCF_Century = 0;
	}
	//
	//屏蔽无效位
	//
	PCF_DataStruct->Years          &= PCF8563_Shield_Years;
	PCF_DataStruct->Months_Century &= PCF8563_Shield_Months_Century;
	PCF_DataStruct->Days           &= PCF8563_Shield_Days;
	PCF_DataStruct->WeekDays       &= PCF8563_Shield_WeekDays;
	
	PCF_DataStruct->Hours          &= PCF8563_Shield_Hours;
	PCF_DataStruct->Minutes        &= PCF8563_Shield_Minutes;
	PCF_DataStruct->Seconds        &= PCF8563_Shield_Seconds;
	
	PCF_DataStruct->Minute_Alarm   &= PCF8563_Shield_Minute_Alarm;
	PCF_DataStruct->Hour_Alarm     &= PCF8563_Shield_Hour_Alarm;
	PCF_DataStruct->Day_Alarm      &= PCF8563_Shield_Day_Alarm;
	PCF_DataStruct->WeekDays_Alarm &= PCF8563_Shield_WeekDays_Alarm;
	
	//
	//判断需要的数据格式
	//
	if (PCF_Format == PCF_Format_BIN)
	{
		PCF_DataStruct->Years           = RTC_Bcd2ToBin(PCF_DataStruct->Years);
		PCF_DataStruct->Months_Century  = RTC_Bcd2ToBin(PCF_DataStruct->Months_Century);
		PCF_DataStruct->Days            = RTC_Bcd2ToBin(PCF_DataStruct->Days);
		PCF_DataStruct->WeekDays        = RTC_Bcd2ToBin(PCF_DataStruct->WeekDays);
		
		PCF_DataStruct->Hours           = RTC_Bcd2ToBin(PCF_DataStruct->Hours);
		PCF_DataStruct->Minutes         = RTC_Bcd2ToBin(PCF_DataStruct->Minutes);
		PCF_DataStruct->Seconds         = RTC_Bcd2ToBin(PCF_DataStruct->Seconds);
		
		PCF_DataStruct->Day_Alarm       = RTC_Bcd2ToBin(PCF_DataStruct->Day_Alarm);
		PCF_DataStruct->WeekDays_Alarm  = RTC_Bcd2ToBin(PCF_DataStruct->WeekDays_Alarm);
		
		PCF_DataStruct->Hour_Alarm      = RTC_Bcd2ToBin(PCF_DataStruct->Hour_Alarm);
		PCF_DataStruct->Minute_Alarm    = RTC_Bcd2ToBin(PCF_DataStruct->Minute_Alarm);
	}
}

/**
   ============================================================================
                      #### 时间信息操作功能函数 ####
   ============================================================================
**/

/**
  *****************************************************************************
  * @Name   : PCF8563写入时间信息
  *
  * @Brief  : none
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *           PCF_DataStruct: 时间结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetTime(unsigned char PCF_Format, _PCF8563_Time_Typedef* PCF_DataStruct)
{
	if (PCF_Format == PCF_Format_BIN)  //十进制格式,需要转换一下
	{
		//
		//判断数值是否在范围之内
		//
		if (PCF_DataStruct->RTC_Hours > 23)    PCF_DataStruct->RTC_Hours   = 0;  //恢复0小时
		if (PCF_DataStruct->RTC_Minutes > 59)  PCF_DataStruct->RTC_Minutes = 0;  //恢复0分钟
		if (PCF_DataStruct->RTC_Seconds > 59)  PCF_DataStruct->RTC_Seconds = 0;  //恢复0秒
		//
		//需要转换一下
		//
		PCF_DataStruct->RTC_Hours   = RTC_BinToBcd2(PCF_DataStruct->RTC_Hours);
		PCF_DataStruct->RTC_Minutes = RTC_BinToBcd2(PCF_DataStruct->RTC_Minutes);
		PCF_DataStruct->RTC_Seconds = RTC_BinToBcd2(PCF_DataStruct->RTC_Seconds);
	}
	//
	//拷贝数据
	//
	buffer[0] = PCF_DataStruct->RTC_Seconds;
	buffer[1] = PCF_DataStruct->RTC_Minutes;
	buffer[2] = PCF_DataStruct->RTC_Hours;
	//
	//写入数据到寄存器
	//
	PCF8563_Write_nByte(PCF8563_Address_Seconds, 3, buffer);
}

/**
  *****************************************************************************
  * @Name   : PCF8563读取时间信息
  *
  * @Brief  : none
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *
  * @Output : PCF_DataStruct: 时间结构指针
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_GetTime(unsigned char PCF_Format, _PCF8563_Time_Typedef* PCF_DataStruct)
{
	/* 读取寄存器数值 */
	PCF8563_Read_nByte(PCF8563_Address_Seconds, 3, buffer);     //调用读多为函数,起始地址为秒,长度3,存入buffer数组
	
	/* 屏蔽无效位,将时分秒寄存器的值分别放入数组 */
	buffer[0] &= PCF8563_Shield_Seconds;
	buffer[1] &= PCF8563_Shield_Minutes;
	buffer[2] &= PCF8563_Shield_Hours;
	
	//判断需要的数据格式,
	if (PCF_Format == PCF_Format_BIN)
	{
		PCF_DataStruct->RTC_Hours   = RTC_Bcd2ToBin(buffer[2]);
		PCF_DataStruct->RTC_Minutes = RTC_Bcd2ToBin(buffer[1]);
		PCF_DataStruct->RTC_Seconds = RTC_Bcd2ToBin(buffer[0]);
	}
	else if (PCF_Format == PCF_Format_BCD)
	{
		//
		//拷贝数据
		//
		PCF_DataStruct->RTC_Hours   = buffer[2];
		PCF_DataStruct->RTC_Minutes = buffer[1];
		PCF_DataStruct->RTC_Seconds = buffer[0];
	}
}

/**
   ============================================================================
                         #### 日期信息操作功能函数 ####
   ============================================================================
**/

/**
  *****************************************************************************
  * @Name   : PCF8563写入日期信息
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *           PCF_Century:    世纪位设定
  *                           = PCF_Century_19xx
  *                           = PCF_Century_20xx
  *           PCF_DataStruct: 日期结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetDate(unsigned char PCF_Format, unsigned char PCF_Century, _PCF8563_Date_Typedef* PCF_DataStruct)
{
	if (PCF_Format == PCF_Format_BIN)  //十进制格式,需要转换一下
	{
		//
		//判断数值是否在范围之内
		//
		if (PCF_DataStruct->RTC_Years > 99)    PCF_DataStruct->RTC_Years    = 0;  //恢复00年
		if (PCF_DataStruct->RTC_Months > 12)   PCF_DataStruct->RTC_Months   = 1;  //恢复1月
		if (PCF_DataStruct->RTC_Days > 31)     PCF_DataStruct->RTC_Days     = 1;  //恢复1日
		if (PCF_DataStruct->RTC_WeekDays > 6)  PCF_DataStruct->RTC_WeekDays = 1;  //恢复星期一
		//
		//需要转换一下
		//
		PCF_DataStruct->RTC_Years    = RTC_BinToBcd2(PCF_DataStruct->RTC_Years);
		PCF_DataStruct->RTC_Months   = RTC_BinToBcd2(PCF_DataStruct->RTC_Months);
		PCF_DataStruct->RTC_Days     = RTC_BinToBcd2(PCF_DataStruct->RTC_Days);
		PCF_DataStruct->RTC_WeekDays = RTC_BinToBcd2(PCF_DataStruct->RTC_WeekDays);
	}
	//
	//判断世纪位
	//
	if (PCF_Century == PCF_Century_19xx)
	{
		PCF_DataStruct->RTC_Months |= PCF_Century_SetBitC;
	}
	else
	{
		PCF_DataStruct->RTC_Months &= ~PCF_Century_SetBitC;
	}
	//
	//数据拷贝
	//
	buffer1[0] = PCF_DataStruct->RTC_Days;
	buffer1[1] = PCF_DataStruct->RTC_WeekDays;
	buffer1[2] = PCF_DataStruct->RTC_Months;
	buffer1[3] = PCF_DataStruct->RTC_Years;
	//
	//写入数据到寄存器
	//
	PCF8563_Write_nByte(PCF8563_Address_Days, 4, buffer1);
}

/**
  *****************************************************************************
  * @Name   : PCF8563读取日期信息
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *
  * @Output : *PCF_Century:   世纪位,0:21世纪;1:20世纪
  *           PCF_DataStruct: 日期结构指针
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_GetDate(unsigned char PCF_Format, unsigned char *PCF_Century, _PCF8563_Date_Typedef* PCF_DataStruct)
{
	//
	//读取全部寄存器数值
	//
	PCF8563_Read_nByte(PCF8563_Address_Days, 4, buffer1);
	//
	//判断世纪位数值
	//
	if (buffer1[2] & PCF_Century_SetBitC)
	{
		*PCF_Century = 1;
	}
	else
	{
		*PCF_Century = 0;
	}
	//
	//屏蔽无效位
	//
	buffer1[0] &= PCF8563_Shield_Days;
	buffer1[1] &= PCF8563_Shield_WeekDays;
	buffer1[2] &= PCF8563_Shield_Months_Century;
	buffer1[3] &= PCF8563_Shield_Years;
	
	//
	//判断需要的数据格式
	//
	if (PCF_Format == PCF_Format_BIN)
	{
		PCF_DataStruct->RTC_Years    = RTC_Bcd2ToBin(buffer1[3]);
		PCF_DataStruct->RTC_Months   = RTC_Bcd2ToBin(buffer1[2]);
		PCF_DataStruct->RTC_Days     = RTC_Bcd2ToBin(buffer1[0]);
		PCF_DataStruct->RTC_WeekDays = RTC_Bcd2ToBin(buffer1[1]);
	}
	else if (PCF_Format == PCF_Format_BCD)
	{
		//
		//拷贝数据
		//
		PCF_DataStruct->RTC_Years    = buffer1[3];
		PCF_DataStruct->RTC_Months   = buffer1[2];
		PCF_DataStruct->RTC_Days     = buffer1[0];
		PCF_DataStruct->RTC_WeekDays = buffer1[1];
	}
}

/**
   ============================================================================
                         #### 闹铃信息操作功能函数 ####
   ============================================================================
**/

/**
  *****************************************************************************
  * @Name   : PCF8563写入闹铃信息
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *           PCF_DataStruct: 闹铃结构指针
  *
  * @Output : none
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_SetAlarm(unsigned char PCF_Format, _PCF8563_Alarm_Typedef* PCF_DataStruct)
{
	unsigned char Alarm_State = 0;
	unsigned char Alarm_Interrupt = 0;  //控制/状态寄存器闹铃中断缓存
	
	if (PCF_Format == PCF_Format_BIN)  //十进制格式,需要转换一下
	{
		//
		//判断数值是否在范围之内
		//
		if (PCF_DataStruct->RTC_AlarmMinutes > 59)  PCF_DataStruct->RTC_AlarmMinutes  = 0;  //恢复0分钟
		if (PCF_DataStruct->RTC_AlarmHours > 23)    PCF_DataStruct->RTC_AlarmHours    = 0;  //恢复0小时
		if (PCF_DataStruct->RTC_AlarmDays > 31)     PCF_DataStruct->RTC_AlarmDays     = 1;  //恢复1日
		if (PCF_DataStruct->RTC_AlarmWeekDays > 6)  PCF_DataStruct->RTC_AlarmWeekDays = 1;  //恢复星期一
		//
		//需要转换一下
		//
		PCF_DataStruct->RTC_AlarmMinutes  = RTC_BinToBcd2(PCF_DataStruct->RTC_AlarmMinutes);
		PCF_DataStruct->RTC_AlarmHours    = RTC_BinToBcd2(PCF_DataStruct->RTC_AlarmHours);
		PCF_DataStruct->RTC_AlarmDays     = RTC_BinToBcd2(PCF_DataStruct->RTC_AlarmDays);
		PCF_DataStruct->RTC_AlarmWeekDays = RTC_BinToBcd2(PCF_DataStruct->RTC_AlarmWeekDays);
	}
	//
	//判断是否开启闹铃选择
	//
	if (PCF_DataStruct->RTC_AlarmNewState == RTC_AlarmNewState_Open)  //只打开闹铃
	{
		Alarm_State = 1;
	}
	else if (PCF_DataStruct->RTC_AlarmNewState == RTC_AlarmNewState_Open_INT_Enable)  //打开闹铃并打开中断输出
	{
		Alarm_State = 2;
	}
	else if (PCF_DataStruct->RTC_AlarmNewState == RTC_AlarmNewState_Close)  //关闭闹铃,并且关闭中断输出
	{
		Alarm_State = 3;
	}
	//
	//读取控制/状态寄存器2值
	//
	Alarm_Interrupt = PCF8563_Read_Byte(PCF8563_Address_Control_Status_2);
	Alarm_Interrupt &= PCF_Alarm_INT_Close;  //先关闭中断输出
	Alarm_Interrupt &= PCF_Control_ClearAF;;  //清除标志
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_2, Alarm_Interrupt);
	
	//
	//根据开启类型进行相应操作
	//
	if (Alarm_State == 1 || Alarm_State == 2)  //打开闹铃
	{
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Days)      PCF_DataStruct->RTC_AlarmDays     &= PCF_Alarm_DaysOpen;  //日期闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Hours)     PCF_DataStruct->RTC_AlarmHours    &= PCF_Alarm_HoursOpen;  //小时闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Minutes)   PCF_DataStruct->RTC_AlarmMinutes  &= PCF_Alarm_MinutesOpen;  //分钟闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_WeekDays)  PCF_DataStruct->RTC_AlarmWeekDays &= PCF_Alarm_WeekDaysOpen;  //分钟闹铃
	}
	if (Alarm_State == 3)  //关闭
	{
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Days)      PCF_DataStruct->RTC_AlarmDays     |= PCF_Alarm_DaysClose;  //日期闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Hours)     PCF_DataStruct->RTC_AlarmHours    |= PCF_Alarm_HoursClose;  //小时闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_Minutes)   PCF_DataStruct->RTC_AlarmMinutes  |= PCF_Alarm_MinutesClose;  //分钟闹铃
		if (PCF_DataStruct->RTC_AlarmType & RTC_AlarmType_WeekDays)  PCF_DataStruct->RTC_AlarmWeekDays |= PCF_Alarm_WeekDaysClose;  //分钟闹铃
	}
	//
	//判断是否开启中断输出
	//
	if (Alarm_State == 2)
	{
		Alarm_Interrupt |= PCF_Alarm_INT_Open;
		Alarm_Interrupt &= PCF_Control_ClearAF;;  //清除标志
	}
	//
	//拷贝数据
	//
	buffer[0] = PCF_DataStruct->RTC_AlarmMinutes;
	buffer[1] = PCF_DataStruct->RTC_AlarmHours;
	buffer[2] = PCF_DataStruct->RTC_AlarmDays;
	buffer[3] = PCF_DataStruct->RTC_AlarmWeekDays;
	//
	//写入数据到寄存器
	//
	PCF8563_Write_nByte(PCF8563_Alarm_Minutes, 4, buffer);
	//
	//写入控制/状态寄存器2数值
	//
	PCF8563_Write_Byte(PCF8563_Address_Control_Status_2, Alarm_Interrupt);
}

/**
  *****************************************************************************
  * @Name   : PCF8563读取闹铃信息
  *
  * @Brief  : 星期数值范围是: 0 ~ 6,十进制格式;只是返回了闹铃寄存器数值,开关位、中断输出什么的不返回
  *
  * @Input  : PCF_Format:     数据格式
  *                           = PCF_Format_BIN
  *                           = PCF_Format_BCD
  *
  * @Output : PCF_DataStruct: 闹铃结构指针
  *
  * @Return : none
  *****************************************************************************
**/
void PCF8563_GetAlarm(unsigned char PCF_Format, _PCF8563_Alarm_Typedef* PCF_DataStruct)
{
	//
	//读取全部寄存器数值
	//
	PCF8563_Read_nByte(PCF8563_Alarm_Minutes, 4, buffer);
	//
	//屏蔽无效位,分钟报警值全部返回
	//
	buffer[0] &= PCF8563_Shield_Minute_Alarm;  //分钟报警值
	buffer[1] &= PCF8563_Shield_Hour_Alarm;  //小时报警值
	buffer[2] &= PCF8563_Shield_Day_Alarm;  //日期报警值
	buffer[3] &= PCF8563_Shield_WeekDays_Alarm;  //星期报警值
	
	//
	//判断需要的数据格式
	//
	if (PCF_Format == PCF_Format_BIN)
	{
		PCF_DataStruct->RTC_AlarmDays     = RTC_Bcd2ToBin(buffer[2]);
		PCF_DataStruct->RTC_AlarmHours    = RTC_Bcd2ToBin(buffer[1]);
		PCF_DataStruct->RTC_AlarmMinutes  = RTC_Bcd2ToBin(buffer[0]);
		PCF_DataStruct->RTC_AlarmWeekDays = RTC_Bcd2ToBin(buffer[3]);
	}
	else if (PCF_Format == PCF_Format_BCD)
	{
		//
		//拷贝数据
		//
		PCF_DataStruct->RTC_AlarmDays     = buffer[2];
		PCF_DataStruct->RTC_AlarmHours    = buffer[1];
		PCF_DataStruct->RTC_AlarmMinutes  = buffer[0];
		PCF_DataStruct->RTC_AlarmWeekDays = buffer[3];
	}
}


/******************************************************************************
* Function Name --> PCF8563_SetDT
* Description   --> 设置日期和时间
* Input         --> none
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void PCF8563_SetDT( void )
{
    _PCF8563_Time_Typedef Time;
    _PCF8563_Date_Typedef Date;
    
    IIC_GPIO_Init( );
    
    Date.RTC_Years = 18;
    Date.RTC_Months = 12;
    Date.RTC_Days = 13;
    Date.RTC_WeekDays = 4;
    
    Time.RTC_Hours = 16;
    Time.RTC_Minutes = 40;
    Time.RTC_Seconds = 6;
    
//    delay_ms( 1000 );
    PCF8563_SetMode( PCF_Mode_Normal );
    
    PCF8563_Stop( );
    
    PCF8563_SetTime( PCF_Format_BIN,&Time );
    PCF8563_SetDate( PCF_Format_BIN,0,&Date );
    
    PCF8563_Start( );
}

/******************************************************************************
* Function Name --> PF8563_GetFunc
* Description   --> 获取日期和时间
* Input         --> PCF_TimeStruct:时间结构体指针
                    PCF_DataStruct:日期结构体指针
* Output        --> none
* Reaturn       --> none 
******************************************************************************/
void PF8563_GetFunc( _PCF8563_Time_Typedef* PCF_TimeStruct, _PCF8563_Date_Typedef* PCF_DataStruct )
{
    PCF8563_GetTime( PCF_Format_BIN, PCF_TimeStruct);
    PCF8563_GetDate( PCF_Format_BIN, 0, PCF_DataStruct );
    
}

HYM8563.H

/**
  *****************************************************************************
  *                            时钟芯片PCF8563驱动
  * @File    : pcf8563.h
  * @By      : shun
  * @Version : V1.0
  * @Date    : 2018 / 12 / 13
  *
  *****************************************************************************
**/


#ifndef _pcf8563_h_ 
#define _pcf8563_h_



/****************************** Support C++ **********************************
**/
#ifdef __cplusplus
	extern "C"{
#endif		
/**
  *****************************************************************************
**/
	

extern unsigned char buffer1[4]; 
extern unsigned char buffer[4];        

/******************************************************************************
                             外部函数头文件
                  应用到不同的外设头文件请在这里修改即可                        
******************************************************************************/

#include "iic.h"

/******************************************************************************
                                 参数宏定义
******************************************************************************/

#define PCF8563_Check_Data                       (unsigned char)0x55  //检测用,可用其他数值

#define PCF8563_Write                            (unsigned char)0xa2  //写命令
#define PCF8563_Read                             (unsigned char)0xa3  //读命令,或者用(PCF8563_Write + 1)

//
//电源复位功能
//
#define PCF8563_PowerResetEnable                 (unsigned char)0x08
#define PCF8563_PowerResetDisable                (unsigned char)0x09

//
//世纪位操作定义
//
#define PCF_Century_SetBitC                      (unsigned char)0x80

#define PCF_Century_19xx                         (unsigned char)0x03
#define PCF_Century_20xx                         (unsigned char)0x04

//
//数据格式
//
#define PCF_Format_BIN                           (unsigned char)0x01
#define PCF_Format_BCD                           (unsigned char)0x02

//
//设置PCF8563模式用
//
#define PCF_Mode_Normal                          (unsigned char)0x05
#define PCF_Mode_EXT_CLK                         (unsigned char)0x06

#define PCF_Mode_INT_Alarm                       (unsigned char)0x07
#define PCF_Mode_INT_Timer                       (unsigned char)0x08

/******************************************************************************
                             参数寄存器地址宏定义
******************************************************************************/

#define PCF8563_Address_Control_Status_1         (unsigned char)0x00  //控制/状态寄存器1
#define PCF8563_Address_Control_Status_2         (unsigned char)0x01  //控制/状态寄存器2

#define PCF8563_Address_CLKOUT                   (unsigned char)0x0d  //CLKOUT频率寄存器
#define PCF8563_Address_Timer                    (unsigned char)0x0e  //定时器控制寄存器
#define PCF8563_Address_Timer_VAL                (unsigned char)0x0f  //定时器倒计数寄存器

#define PCF8563_Address_Years                    (unsigned char)0x08  //年
#define PCF8563_Address_Months                   (unsigned char)0x07  //月
#define PCF8563_Address_Days                     (unsigned char)0x05  //日
#define PCF8563_Address_WeekDays                 (unsigned char)0x06  //星期
#define PCF8563_Address_Hours                    (unsigned char)0x04  //小时
#define PCF8563_Address_Minutes                  (unsigned char)0x03  //分钟
#define PCF8563_Address_Seconds                  (unsigned char)0x02  //秒

#define PCF8563_Alarm_Minutes                    (unsigned char)0x09  //分钟报警
#define PCF8563_Alarm_Hours                      (unsigned char)0x0a  //小时报警
#define PCF8563_Alarm_Days                       (unsigned char)0x0b  //日报警
#define PCF8563_Alarm_WeekDays                   (unsigned char)0x0c  //星期报警

/******************************************************************************
                               参数屏蔽宏定义
******************************************************************************/

#define PCF8563_Shield_Control_Status_1          (unsigned char)0xa8
#define PCF8563_Shield_Control_Status_2          (unsigned char)0x1f

#define PCF8563_Shield_Seconds                   (unsigned char)0x7f
#define PCF8563_Shield_Minutes                   (unsigned char)0x7f
#define PCF8563_Shield_Hours                     (unsigned char)0x3f

#define PCF8563_Shield_Days                      (unsigned char)0x3f
#define PCF8563_Shield_WeekDays                  (unsigned char)0x07
#define PCF8563_Shield_Months_Century            (unsigned char)0x1f
#define PCF8563_Shield_Years                     (unsigned char)0xff

#define PCF8563_Shield_Minute_Alarm              (unsigned char)0x7f
#define PCF8563_Shield_Hour_Alarm                (unsigned char)0x3f
#define PCF8563_Shield_Day_Alarm                 (unsigned char)0x3f
#define PCF8563_Shield_WeekDays_Alarm            (unsigned char)0x07

#define PCF8563_Shield_CLKOUT_Frequency          (unsigned char)0x03
#define PCF8563_Shield_Timer_Control             (unsigned char)0x03
#define PCF8563_Shield_Timer_Countdown_Value     (unsigned char)0xff

/******************************************************************************
                              PCF8563寄存器结构定义                          
******************************************************************************/

/**
   ==================================================================
                               全部寄存器结构
   ==================================================================
**/
typedef struct
{
	unsigned char Control_Status_1;      //控制寄存器1
	unsigned char Control_Status_2;      //控制寄存器2
	unsigned char Seconds;               //秒寄存器
	unsigned char Minutes;               //分钟寄存器
	unsigned char Hours;                 //小时寄存器
	unsigned char Days;                  //日期寄存器
	unsigned char WeekDays;              //星期寄存器,数值范围:0 ~ 6
	unsigned char Months_Century;        //月份寄存器,bit7为世纪位,0:指定世纪数为20xx;1:指定世纪数为19xx
	unsigned char Years;                 //年寄存器
	unsigned char Minute_Alarm;          //分钟报警寄存器
	unsigned char Hour_Alarm;            //小时报警寄存器
	unsigned char Day_Alarm;             //日期报警寄存器
	unsigned char WeekDays_Alarm;        //星期报警寄存器,数值范围:0 ~ 6
	unsigned char CLKOUT_Frequency;      //频率管脚输出控制寄存器
	unsigned char Timer_Control;         //定时器控制寄存器
	unsigned char Timer_Countdown_Value; //定时器计数寄存器
}_PCF8563_Register_Typedef;

/**
   ==================================================================
                               时间信息结构
   ==================================================================
**/
typedef struct
{
	unsigned char RTC_Hours;    //小时
	unsigned char RTC_Minutes;  //分钟
	unsigned char RTC_Seconds;  //秒钟
	unsigned char Reseved;      //保留
}_PCF8563_Time_Typedef;


/**
   ==================================================================
                               日期信息结构
   ==================================================================
**/
typedef struct
{
	unsigned char RTC_Years;    //年份
	unsigned char RTC_Months;   //月份
	unsigned char RTC_Days;     //日期
	unsigned char RTC_WeekDays; //星期,数值范围:0 ~ 6
}_PCF8563_Date_Typedef;



/**
   ==================================================================
                               闹铃信息结构
   ==================================================================
**/
typedef struct
{
	unsigned short Reseved;             //保留
	unsigned char RTC_AlarmDays;        //日期闹铃
	unsigned char RTC_AlarmWeekDays;    //星期闹铃,数值范围:0 ~ 6
	unsigned char RTC_AlarmHours;       //小时闹铃
	unsigned char RTC_AlarmMinutes;     //分钟闹铃
	unsigned char RTC_AlarmNewState;    //闹铃开关
                                        //其值有RTC_AlarmNewState_Open、RTC_AlarmNewState_Close、RTC_AlarmNewState_Open_INT_Enable
                                        //只使用其中一个即可
	unsigned char RTC_AlarmType;        //报警类型,
                                        //其值有RTC_AlarmType_Minutes、RTC_AlarmType_Hours、RTC_AlarmType_Days、RTC_AlarmType_WeekDays
                                        //多个报警类型打开,请用或关系合并
}_PCF8563_Alarm_Typedef;

//
//闹铃开关
//
#define RTC_AlarmNewState_Open                   (u8)0x01
#define RTC_AlarmNewState_Close                  (u8)0x02  //闹铃关闭,并且关闭中断输出
#define RTC_AlarmNewState_Open_INT_Enable        (u8)0x04  //闹铃开启并开启中断输出
//
//定义闹铃类型
//
#define RTC_AlarmType_Minutes                    (unsigned char)0x01
#define RTC_AlarmType_Hours                      (unsigned char)0x02
#define RTC_AlarmType_Days                       (unsigned char)0x04
#define RTC_AlarmType_WeekDays                   (unsigned char)0x08

/**
   ==================================================================
                               频率输出信息结构
   ==================================================================
**/
typedef struct
{
	unsigned char CLKOUT_Frequency;  //输出频率选择
	                                 //PCF_CLKOUT_F32768 --> 输出32.768KHz
                                     //PCF_CLKOUT_F1024  --> 输出1024Hz
                                     //PCF_CLKOUT_F32    --> 输出32Hz
                                     //PCF_CLKOUT_F1     --> 输出1Hz
	unsigned char CLKOUT_NewState;   //输出状态
	                                 //PCF_CLKOUT_Close  --> 输出被禁止并设成高阻抗
	                                 //PCF_CLKOUT_Open   --> 输出有效
}_PCF8563_CLKOUT_Typedef;

//
//频率输出寄存器 --> 0x0d
//
#define PCF_CLKOUT_Open                          (unsigned char)(1<<7)     //CLKOUT输出有效
#define PCF_CLKOUT_Close                         (unsigned char)(~(1<<7))  //CLKOUT输出被禁止并设成高阻抗

#define PCF_CLKOUT_F32768                        (unsigned char)0x00  //输出32.768KHz
#define PCF_CLKOUT_F1024                         (unsigned char)0x01  //输出1024Hz
#define PCF_CLKOUT_F32                           (unsigned char)0x02  //输出32Hz
#define PCF_CLKOUT_F1                            (unsigned char)0x03  //输出1Hz

/**
   ==================================================================
                               定时器信息结构
   ==================================================================
**/
typedef struct
{
	unsigned char RTC_Timer_Value;      //定时器计数器数值,设置定时时长,不需要的直接填0即可
	unsigned char RTC_Timer_Frequency;  //定时器工作频率
	                                    //PCF_Timer_F4096 --> 定时器时钟频率为4096Hz
	                                    //PCF_Timer_F64   --> 定时器时钟频率为64Hz
	                                    //PCF_Timer_F1    --> 定时器时钟频率为1Hz
	                                    //PCF_Timer_F160  --> 定时器时钟频率为1/60Hz
	unsigned char RTC_Timer_NewState;   //开启状态
	                                    //PCF_Timer_Close  --> 关闭
	                                    //PCF_Timer_Open   --> 开启
	unsigned char RTC_Timer_Interrupt;  //是否设置中断输出
	                                    //PCF_Time_INT_Close --> 关闭
	                                    //PCF_Time_INT_Open  --> 开启
}_PCF8563_Timer_Typedef;

//
//定时器控制寄存器 --> 0x0e
//
#define PCF_Timer_Open                           (unsigned char)(1<<7)     //定时器有效
#define PCF_Timer_Close                          (unsigned char)(~(1<<7))  //定时器无效

#define PCF_Timer_F4096                          (unsigned char)0x00  //定时器时钟频率为4096Hz
#define PCF_Timer_F64                            (unsigned char)0x01  //定时器时钟频率为64Hz
#define PCF_Timer_F1                             (unsigned char)0x02  //定时器时钟频率为1Hz
#define PCF_Timer_F160                           (unsigned char)0x03  //定时器时钟频率为1/60Hz

//
//中断输出开关
//
#define PCF_Time_INT_Open                        (unsigned char)(1<<0)     //定时器中断有效
#define PCF_Time_INT_Close                       (unsigned char)(~(1<<0))  //定时器中断无效

/******************************************************************************
                                 参数宏定义
******************************************************************************/

//
//控制/状态寄存器1 --> 0x00
//
#define PCF_Control_Status_NormalMode            (unsigned char)(~(1<<7))  //普通模式
#define PCF_Control_Status_EXT_CLKMode           (unsigned char)(1<<7)     //EXT_CLK测试模式
#define PCF_Control_ChipRuns                     (unsigned char)(~(1<<5))  //芯片运行
#define PCF_Control_ChipStop                     (unsigned char)(1<<5)     //芯片停止运行,所有芯片分频器异步置逻辑0
#define PCF_Control_TestcClose                   (unsigned char)(~(1<<3))  //电源复位功能失效(普通模式时置逻辑0)
#define PCF_Control_TestcOpen                    (unsigned char)(1<<3)     //电源复位功能有效

//
//控制/状态寄存器2 --> 0x01
//
#define PCF_Control_TI_TF1                       (unsigned char)(~(1<<4))  //当TF有效时INT有效,(取决于TIE的状态)
#define PCF_Control_TI_TF2                       (unsigned char)(1<<4)     //INT脉冲有效,(取决于TIE的状态)
                                                                           //注意:若AF和AIE有有效时,则INT一直有效
#define PCF_Control_ClearAF                      (unsigned char)(~(1<<3))  //清除报警
#define PCF_Control_ClearTF                      (unsigned char)(~(1<<2))
                                                                           //当报警发生时,AF被值逻辑1;在定时器倒计数结束时,
                                                                           //TF被值逻辑1,他们在被软件重写前一直保持原有值,
                                                                           //若定时器和报警中断都请求时,中断源有AF和TF决定,
                                                                           //若要使清除一个标志位而防止另一标志位被重写,应运用逻辑
                                                                           //指令AND
#define PCF_Alarm_INT_Open                       (unsigned char)(1<<1)     //报警中断有效
#define PCF_Alarm_INT_Close                      (unsigned char)(~(1<<1))  //报警中断无效

//
//秒寄存器 --> 0x02
//
#define PCF_Accuracy_ClockNo                     (unsigned char)(1<<7)     //不保证准确的时钟/日历数据
#define PCF_Accuracy_ClockYes                    (unsigned char)(~(1<<7))  //保证准确的时钟/日历数据

//
//分钟闹铃寄存器 --> 0x09
//
#define PCF_Alarm_MinutesOpen                    (unsigned char)(~(1<<7))  //分钟报警有效
#define PCF_Alarm_MinutesClose                   (unsigned char)(1<<7)     //分钟报警无效

//
//小时闹铃寄存器 --> 0x0a
//
#define PCF_Alarm_HoursOpen                      (unsigned char)(~(1<<7))  //小时报警有效
#define PCF_Alarm_HoursClose                     (unsigned char)(1<<7)     //小时报警无效

//
//日期闹铃寄存器 --> 0x0b
//
#define PCF_Alarm_DaysOpen                       (unsigned char)(~(1<<7))  //日报警有效
#define PCF_Alarm_DaysClose                      (unsigned char)(1<<7)     //日报警无效

//
//星期闹铃寄存器 --> 0x0c
//
#define PCF_Alarm_WeekDaysOpen                   (unsigned char)(~(1<<7))  //星期报警有效
#define PCF_Alarm_WeekDaysClose                  (unsigned char)(1<<7)     //星期报警无效

/******************************************************************************
                                  外部功能函数                      
******************************************************************************/

void          PCF8563_Write_Byte                 (unsigned char REG_ADD, unsigned char dat);  //PCF8563某寄存器写入一个字节数据
unsigned char PCF8563_Read_Byte                  (unsigned char REG_ADD);  //PCF8563某寄存器读取一个字节数据
void          PCF8563_Write_nByte                (unsigned char REG_ADD, unsigned char num, unsigned char *pBuff);  //PCF8563写入多组数据
void          PCF8563_Read_nByte                 (unsigned char REG_ADD, unsigned char num, unsigned char *pBuff);  //PCF8563读取多组数据

unsigned char PCF8563_Check                      (void);  //PCF8563检测是否存在
void          PCF8563_Start                      (void);  //PCF8563启动
void          PCF8563_Stop                       (void);  //PCF8563停止

void          PCF8563_SetMode                    (unsigned char Mode);  //PCF8563设置运行模式
void          PCF8563_SetPowerReset              (unsigned char NewState);  //PCF8563设置电源复位功能开启与关闭

void          PCF8563_SetCLKOUT                  (_PCF8563_CLKOUT_Typedef* PCF_CLKOUTStruct);  //PCF8563设置输出频率
void          PCF8563_SetTimer                   (_PCF8563_Timer_Typedef* PCF_TimerStruct);  //PCF8563设置定时器

void          PCF8563_Set_Times                  (unsigned char PCF_Format,\
                                                  unsigned char PCF_Century,\
	                                              unsigned char Year, unsigned char Month, unsigned char Date, unsigned char Week,\
                                                  unsigned char Hour, unsigned char Minute);  //设置时间,主要用于后台调用,或者初始化时间用

void          PCF8563_SetRegister                (unsigned char PCF_Format, unsigned char PCF_Century, _PCF8563_Register_Typedef* PCF_DataStruct);  //PCF8563写入寄存器
void          PCF8563_GetRegister                (unsigned char PCF_Format, unsigned char *PCF_Century, _PCF8563_Register_Typedef* PCF_DataStruct);  //PCF8563读取寄存器

void          PCF8563_SetTime                    (unsigned char PCF_Format, _PCF8563_Time_Typedef* PCF_DataStruct);  //PCF8563写入时间信息
void          PCF8563_GetTime                    (unsigned char PCF_Format, _PCF8563_Time_Typedef* PCF_DataStruct);  //PCF8563读取时间信息

void          PCF8563_SetDate                    (unsigned char PCF_Format, unsigned char PCF_Century, _PCF8563_Date_Typedef* PCF_DataStruct);  //PCF8563写入日期信息
void          PCF8563_GetDate                    (unsigned char PCF_Format, unsigned char *PCF_Century, _PCF8563_Date_Typedef* PCF_DataStruct);  //PCF8563读取日期信息

void          PCF8563_SetAlarm                   (unsigned char PCF_Format, _PCF8563_Alarm_Typedef* PCF_DataStruct);  //PCF8563写入闹铃信息
void          PCF8563_GetAlarm                   (unsigned char PCF_Format, _PCF8563_Alarm_Typedef* PCF_DataStruct);  //PCF8563读取闹铃信息
                                                  
void PCF8563_SetDT( void );   
void PF8563_GetFunc( _PCF8563_Time_Typedef* PCF_TimeStruct, _PCF8563_Date_Typedef* PCF_DataStruct );                                                  


/**
  ****************************** Support C++ **********************************
**/
#ifdef __cplusplus
	}
#endif
/**
  *****************************************************************************
**/


#endif  /* end pcf8563.h */

主函数

void set_time_example() {
    // 定义存储时间的结构体
    _PCF8563_Time_Typedef current_time;

    // 填充时间信息
    current_time.RTC_Hours = 15;     // 时
    current_time.RTC_Minutes = 0;   // 分
    current_time.RTC_Seconds = 0;    // 秒

    // 设置当前时间,数据格式为十进制
    PCF8563_SetTime(PCF_Format_BIN, &current_time);

    // 打印设置后的时间
//    printf("已设置时间:%02d:%02d:%02d\n", 
//           current_time.RTC_Hours, current_time.RTC_Minutes, current_time.RTC_Seconds);
}


/*-----------------------------------------------------------------------------------------------------------
*函数名称: Task_SynchEventHandle(void *pdata)
*功能描述: --任务同步事件处理函数
*输    入: *pdata 任务运行参数
*输    出: None
*返 回 值: None
*作    者: David Wang
*创建日期: 2015-03-10
*------------------------------------------------------------------------------------------------------------
*修 改 人: 
*修改日期: 
*修改描述: 
-----------------------------------------------------------------------------------------------------------*/
void set_date_example() {
    // 定义存储日期的结构体
    _PCF8563_Date_Typedef current_date;

    // 填充日期信息
    current_date.RTC_Years = 24;        // 年份,表示 2024 年
    current_date.RTC_Months = 4;        // 月份,表示 4 月
    current_date.RTC_Days = 24;         // 日,表示 25 日
    current_date.RTC_WeekDays = 3;      // 星期二,星期数值为 2

    // 设置当前日期,数据格式为十进制,世纪位为 20xx
    PCF8563_SetDate(PCF_Format_BIN, PCF_Century_20xx, &current_date);

    // 打印设置后的日期
//    printf("已设置日期:%02d-%02d-%02d 星期%d\n", 
//           2000 + current_date.RTC_Years, current_date.RTC_Months, current_date.RTC_Days,
//           current_date.RTC_WeekDays);
}


/*-----------------------------------------------------------------------------------------------------------
*函数名称: Task_SynchEventHandle(void *pdata)
*功能描述: --任务同步事件处理函数
*输    入: *pdata 任务运行参数
*输    出: None
*返 回 值: None
*作    者: David Wang
*创建日期: 2015-03-10
*------------------------------------------------------------------------------------------------------------
*修 改 人: 
*修改日期: 
*修改描述: 
-----------------------------------------------------------------------------------------------------------*/
void RTC_SynchEventHandle(void *pdata)
{
	   
    _PCF8563_Time_Typedef currentTime; // 定义存储时间的结构体
    _PCF8563_Date_Typedef currentDate;// 定义存储日期的结构体       
    unsigned char PCF_Century;    // 定义世纪位 
	
//	set_time_example();//设置时间
	set_date_example();//设置日期
	
    if (!PCF8563_Check()) // 检测时钟芯片是否存在
	 {
			printf("PCF8563时钟芯片存在\r\n");
			 
			// 设置输出频率为 32.768kHz 并打开输出
			_PCF8563_CLKOUT_Typedef   CLKOUT_Config;
			CLKOUT_Config.CLKOUT_Frequency = PCF_CLKOUT_F32768;
			CLKOUT_Config.CLKOUT_NewState = PCF_CLKOUT_Open;
			PCF8563_SetCLKOUT(&CLKOUT_Config);
			   
			PCF8563_Start();// 启动时钟
			Delay_ms(10);
		 
			while(1)
			{
				// 读取时间
				PCF8563_GetTime(1, &currentTime);
				PCF8563_GetDate(1, &PCF_Century, &currentDate);
				// 打印年月日时分秒
				printf("当前时间:%d-%02d-%02d 星期% d %02d:%02d:%02d\r\n",
					   2000 + currentDate.RTC_Years, currentDate.RTC_Months, currentDate.RTC_Days,currentDate.RTC_WeekDays,
					   currentTime.RTC_Hours, currentTime.RTC_Minutes, currentTime.RTC_Seconds);
				Delay_ms(1000);
			}			

     } 
	else 
	 {
         printf("PCF8563时钟芯片不存在\n");
     }

}

实现实时时钟,电源拔插时间不重置(内置电池供电维持时间变化)。功能有查看日期,查看星期,查看闹钟和分别的调整时间,调整日期,调整闹钟,调整星期。且默认情况下不可以调整,当按下可调控键之后才可以调整、再次按可调控键关闭变为不可调整状态。还有整点报时功能(有个小瑕疵就是闹钟正好是整点的时候和这个整点报时同时间的时候不会报时和闹钟,这个很容易改好,因为下午3点要答辩了,懒得改了机子老是写不进去,学校穷便宜机子没办法)。然后这个闹钟可以设置星期几几点闹也可以设置为普通的每天的这个时间点闹铃,这些都是可以调控的。时钟所有的功能都有,只差一个秒表,,这个很简单,,,外部中断来一个或者定时器T1中断来一个都可以,我没弄,因为我这个已经代码很长了,头疼、加中断还得加显示函数和秒表变化函数if分大于60 时++啥的,但因为这个采用的显示是低四位高四位控制的,我强行加一个也比较麻烦所有就没加了。欢迎下载干货,难看懂的都有备注,写了断断续续一周+时间左右(恕在下才疏学浅,因为书上上课的时候没学过I2C总线和pcf8563所以写的比较久。)部分代码如下: #define MAIN_Fosc 22118400L //定义主时钟 频率也是计数计时周期一秒的计数值 #include "STC15Fxxxx.H" /***********************************************************/ #define DIS_DOT 0x20 #define DIS_BLACK 0x10 #define DIS_ 0x11 /****************************** 用户定义宏***********************************/ #define Timer0_Reload (65536UL -(MAIN_Fosc / 1000)) //Timer 0 中断频率,1000次/秒 频率倍数计数即周期 周期为1秒 除以一千就是1000次每秒 /*****************************************************************************/ /************* 本地常量声明 **************/ u8 code t_display[]={ //标准字库 // 0 1 2 3 4 5 6 7 8 9 A B C D E F //共阴 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71, //black - H J K L N o P U t G Q r M y 0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e, 0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46}; //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1 u8code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //位码 取反就是书上213面 0从低位到高位 /************* IO口定义 **************/ sbit P_HC595_SER = P4^0; //pin 14 SER datainput sbit P_HC595_RCLK = P5^4; //pin 12 RCLk store(latch) clock sbit P_HC595_SRCLK = P4^3; //pin 11 SRCLK Shift data clock sbit led=P1^7; sbit led1=P4^7; sbit key=P3^2; /************* 本地变量声明 **************/ u8 LED8[8]; //显示缓冲 u8 display_index; //显示位索引 bit B_1ms; //1ms标志 u8IO_KeyState, IO_KeyState1, IO_KeyHoldCnt; //行列键盘变量 u8 KeyHoldCnt; //键按下计时 u8 KeyCode; //给用户使用的键码, 1~16有效 u8 cnt50ms; u8hello; u8nao; u8minute2; u8KeyCode0; u8 hour,hour1,minute,minute1,second,day,week,week1,month,year; //RTC变量 u16 msecond; u16msecond1; u8hello; u8naofu; u8zhuangtai; u8xunhuan; u8tuinao; //闹钟控制开启退出 u8xinqinao;//星期·闹钟 /************* 本地函数声明 **************/ void CalculateAdcKey(u16 adc); void IO_KeyScan(void); //50ms call void WriteNbyte(u8 addr, u8 *p, u8 number); void ReadNbyte( u8 addr, u8 *p, u8 number); void DisplayRTC(void); void DisplayRTC1(void); void DisplayRTC2(void); void ReadRTC(void);//读取时钟 void ReadRTC1(void); void ReadRTC2(void); void ReadRTC3(void); void WriteRTC(void); void WriteRTC1(void); void WriteRTC2(void); void WriteRTC3(void); void DisplayRTC3(void); void DisplayRTC4(void); void DisplayRTC5(void); /**************** 外部函数声明和外部变量声明*****************/ /**********************************************/ voidmain(void) { u8 i; P0M1= 0; P0M0 = 0; //设置为准双向口 P1M1= 0; P1M0 = 0; //设置为准双向口 P2M1= 0; P2M0 = 0; //设置为准双向口 P3M1= 0; P3M0 = 0; //设置为准双向口 P4M1= 0; P4M0 = 0; //设置为准双向口 P5M1= 0; P5M0 = 0; //设置为准双向口 P6M1= 0; P6M0 = 0; //设置为准双向口 P7M1= 0; P7M0 = 0; //设置为准双向口 display_index= 0; AUXR= 0x80;//T0时钟无分频 TMOD=0x00; //Timer0 set as 1T, 16 bits timer auto-reload,T0时钟无分频,16位自动重装 TH0= (u8)(Timer0_Reload / 256); //定时器取其高低8位为状态值 TL0= (u8)(Timer0_Reload % 256); ET0= 1; //Timer0 interrupt enable T0中断允许 TR0= 1; //Tiner0 run T0启动 EA= 1; //打开总中断 ,总中断允许 hello=0; if(nao==1){}//断电重置 elseif(nao==2){} else { nao=0; } for(i=0;i= 60) F0 = 1; //错误 if(minute>= 60) F0 = 1; //错误 if(hour >= 24) F0= 1; //错误 if(F0==1) //有错误, 默认12:00:00 { second= 0; minute= 0; hour = 12; WriteRTC(); } if(day>=32) F0=2; if(week>=8) F0=2; if(month>=13)F0=2; if(year>=100)F0=2; if(F0==2) //有错误, 默认12:00:00 { day=6; week=3; month=6; year=18; WriteRTC1(); } if(minute1>= 60) F0 = 3; //错误 if(hour1 >= 24) F0= 3; //错误 if(F0==3) { minute1=30; hour1=7; WriteRTC2(); } if(week1>=8) { WriteRTC3(); } DisplayRTC(); KeyHoldCnt= 0; //键按下计时 KeyCode= 0; //给用户使用的键码,1~16有效 IO_KeyState= 0; IO_KeyState1= 0; IO_KeyHoldCnt= 0; cnt50ms= 0; zhuangtai=0; KeyCode0=0; tuinao=0; minute2=61; naofu=0;//控制闹钟加1加5与分钟同步 xunhuan=0;//控制循环闹钟 xinqinao=0;//星期闹钟控制 if(msecond1==0){} else { msecond1=0; } while(1) { if(B_1ms) //1ms到 { B_1ms= 0; if(++msecond>= 500) //1秒到 刷新时钟 { if(hello==0) { ReadRTC(); DisplayRTC(); if(minute==0) //整点报时 { if(hour==hour1) { if(minute==minute1) {}else{ led1=0; } }else { led1=0; } } else{ led1=1; } if(hour==hour1) //闹钟实现块 { if(second==0)//保证和时钟分钟同步++乘其下一分钟前进行+5 +1操作 { msecond1=0; naofu=1; } else { if(naofu==1) { if(++msecond1>=60) {msecond1=0; naofu=0; } } } if(minute==minute1-1)//取出闹钟分钟值 { ReadRTC2(); minute2=minute1; }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值