标题:
关于STM32单片机PCF8563 IIC驱动 pcf8563.c pcf8563.h文件
[打印本页]
作者:
Aisyle
时间:
2024-4-28 11:33
标题:
关于STM32单片机PCF8563 IIC驱动 pcf8563.c pcf8563.h文件
代码直接贴出来嗷 需要的友友直接下载就好了
pcf8563.c
/**
*****************************************************************************
* 时钟芯片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
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
*****************************************************************************
**/
复制代码
这边有点乱码 我就直接上传文件了 有什么问题欢迎讨论
51hei.png
(2.54 KB, 下载次数: 36)
下载附件
2024-4-28 14:49 上传
注意代码里面只有上图2个文件,请自行移植到各MCU系统中去:
c文件和h文件下载.7z
(9.45 KB, 下载次数: 13)
2024-4-28 14:51 上传
点击文件名下载附件
部分代码
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1