代码直接贴出来嗷 需要的友友直接下载就好了
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
- *****************************************************************************
- **/
复制代码
这边有点乱码 我就直接上传文件了 有什么问题欢迎讨论
注意代码里面只有上图2个文件,请自行移植到各MCU系统中去:
c文件和h文件下载.7z
(9.45 KB, 下载次数: 13)
|