/**
*****************************************************************************
* 时钟芯片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));
}
/******************************************************************************
* @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