当前位置: 首页 > ai >正文

51单片机读取PCF8563时钟芯片

PCF8563时钟芯片介绍

PCF8563 有16 个8位寄存器:一个可自动增量的地址寄存器,一个内置32.768KHz的振荡器(带有一个内部集成的电容),一个分频器(用于给实时时钟RTC 提供源时钟),一个可编程时钟输出,一个定时器,一个报警器,一个掉电检测器和一个 400KHz I2C总线接口。 所有16个寄存器设计成可寻址的8位并行寄存器,但不是所有位都有用。前两个寄存器(内存地址00H,01H)用于控制寄存器和状态寄存器,内存地址02H~08H用于时钟计数器(秒~年计数器),地址 09H~0CH 用于报警寄存器(定义报警条件),地址 0DH 控制
CLKOUT管脚的输出频率,地址0EH 和0FH分别用于定时器控制寄存器和定时器寄存器。秒、分钟、小时、日、月、年、分钟报警、小时报警、日报警寄存器,编码格式为 BCD,星期和星期报警寄存器不以BCD格式编码。
PCF8563的通信方式为IIC,管脚如下,其中主要用到的引脚为电源引脚、SCL和SDA引脚。
在这里插入图片描述
主要的寄存器如下,如果你只是需要进行时间的设置与读取的话,那么只需要看地址0x02到0x08的寄存器,它们分别存储的内容为秒,分,时,日,星期,月,年。
在这里插入图片描述
在这里插入图片描述
本文实现的功能很简单,主要就是对这些时间寄存器的内容进行读写,那么熟悉IIC的同学相信一定知道接下来要介绍的是什么了,那就是PCF8563的读写地址。众所周知,在IIC通信中,每一个设备都要有一个读写地址,PCF8563的读地址为0xA2,写地址为0xA3。知道读写地址以及我们要操作的芯片内部寄存器地址后就十分简单了。但是先不要着急,我们注意到PCF8563的0x00地址寄存器中,有一位STOP位,这个位是用于控制PCF8563的时钟启停的,0启动,1停止,因此如果我们不知道现在芯片时钟是开始还是停止状态,那么最好启动一下,向0x00地址发送0x00即可启动,停止是向0x00发送0x20。一般不需要多次发送开始命令,只要发送过一次开始命令,那么时钟就会一直运行,只要发送过一次停止命令,时钟就不会运行了。
这里额外说一下,PCF8563可以进行连续读写,也就是说,如果你要从0x02开始读,如果你不发送停止命令,那么它会按照地址顺序依次将数据都返回给你,当然,这里我们不使用这种连续读取的方法,我们还是用老办法,一个地址一个地址的读。感兴趣的同学可以自己尝试一下连续读。还有一点需要注意的是,虽然芯片的0x06寄存器存储的是星期信息,但是它不是自动计算的,你需要手动赋值,而且就算你赋值不对它也不会检查,其他位也是类似的,并且如果你赋值超过合法的范围可能会导致时钟出错,因此,需要注意这个地方。

代码

i2c.c

#include <STC8.H>
#include"intrins.h"// 板载芯片由于不需要杜邦线连接 因此信号传输速度较快 使用1us延时即可
// 使用外接PCF8563芯片时 不能使用这么短的IIC延时 应该增加到10us
sbit SCL=P6^1;
sbit SDA=P6^0;
//sbit SCL=P2^5;
//sbit SDA=P2^4;
void Delay10us()		//@12.000MHz
{unsigned char i;_nop_();_nop_();i = 27;while (--i);
}void I2CStart(void)
{SCL=0;SDA=1;SCL=1;Delay10us();SDA=0;SCL=0;
}
void I2CStop()
{SCL=0;SDA=0;SCL=1;Delay10us();SDA=1;SCL=0;
}
// 在Write和Read操作中 8次对SCL时序进行操作后都立刻进行一次延时防止出现bug
void I2CSendByte(unsigned char Byte)
{unsigned char i;for(i=0;i<8;i++){SCL=0;if(Byte&(0x80>>i))SDA=1;elseSDA=0;Delay10us();SCL=1;Delay10us();}SCL=0;SDA=1;
}
unsigned char I2CReceiveByte()
{unsigned char Byte=0x00,i;for(i=0;i<8;i++){SCL=0;// 注意此处的延时!!!对于STC8A8K64S4A12这款芯片 需要在此处加上延时才能读取正确// 否则读取到的只有数据的第一位 原因未知Delay10us();SCL=1;Delay10us();if(SDA)Byte|=(0x80>>i);}SCL=0;SDA=1;return Byte;
}
void I2CSendAck(unsigned char ackbit)
{SCL=0;SDA=ackbit;SCL=1;Delay10us();SCL=0;SDA=1;
}
unsigned char I2CWaitAck()
{unsigned char ack;SCL=0;SCL=1;Delay10us();if(SDA)ack=0;elseack=1;SCL=0;SDA=1;return ack;
}

i2c.h

#ifndef __I2C_H__
#define __I2C_H__void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);#endif

PCF8563.c

#include"I2C.h"unsigned char PCF8563_ReadByte(unsigned char addr)
{unsigned char Byte=0x00;I2CStart();I2CSendByte(0xA2);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CStart();I2CSendByte(0xA3);I2CWaitAck();Byte=I2CReceiveByte();// 注意!!!这里一定要Ack 1I2CSendAck(1);I2CStop();return Byte;
}
void PCF8563_WriteByte(unsigned char addr,Byte)
{I2CStart();I2CSendByte(0xA2);I2CWaitAck();I2CSendByte(addr);I2CWaitAck();I2CSendByte(Byte);I2CWaitAck();I2CStop();
}
void PCF8563_Init()
{PCF8563_WriteByte(0x00,0x00);
}void PCF8563_SetTime(unsigned char*times)
{unsigned char i;for(i=0;i<8;i++){PCF8563_WriteByte(0x02+i,times[i]);}
}

main.c

#include <STC8.H>
#include"PCF8563.h"
#include"LCD12864.h"unsigned char cnt,year,month,day,hour,minute,second,D;
void Timer0Init(void)		//5毫秒@12.000MHz
{AUXR |= 0x80;		//定时器时钟1T模式TMOD &= 0xF0;		//设置定时器模式TL0 = 0xA0;		//设置定时初值TH0 = 0x15;		//设置定时初值TF0 = 0;		//清除TF0标志TR0 = 1;		//定时器0开始计时
}
/*
程序说明
程序实现了时间的设置读取与显示
当设置好时间后 即可进行读取 并在LCD12864上显示 
第一行显示字符串Time 第二行显示年月日
第三行显示时分秒
注意 PCF8563_SetTime执行过一次后就要注释掉然后再次写入hex文件
否则每次开机都是从初始时间开始
使用外接PCF8563时 即使单片机断电 PCF的时钟依旧会继续执行 因为有外部电源
*/
void main()
{//                      秒   分   时   日  星期  月   年// 分别对应的寄存器地址0x02  03   04   05   06   07   08unsigned char times[]={0x00,0x17,0x10,0x29,0x02,0x10,0x24};Timer0Init();ET0=1;EA=1;PCF8563_Init();LCD12864_Init();LCD12864_ShowStr(0,0,"Time");//PCF8563_SetTime(times);while(1){;}
}
// 如果要在中断中显示时间 则设置的LCD刷新时间不能太快
// 否则会显示错误 因为LCD本身的读写也需要时间
void Timer0Routine()interrupt 1
{cnt++;if(cnt<5)return;elsecnt=0;second=PCF8563_ReadByte(0x02);LCD12864_ShowH(2,4,second);minute=PCF8563_ReadByte(0x03);LCD12864_ShowH(2,2,minute);hour=PCF8563_ReadByte(0x04);LCD12864_ShowH(2,0,hour);day=PCF8563_ReadByte(0x05);LCD12864_ShowH(1,4,day);month=PCF8563_ReadByte(0x07);LCD12864_ShowH(1,2,month);year=PCF8563_ReadByte(0x08);LCD12864_ShowH(1,0,year);D=PCF8563_ReadByte(0x06);LCD12864_SetCursor(3,0);LCD12864_WriteData(D+'0');
}

重要提醒!!!,使用IIC读取PCF8563单个时间数据后,最后一步SendAck(1)输入的是1,而不是0!!!输入1代表我已经结束当前这次的读取了,不用再继续给我发送数据了,因为PCF8563是自动会返回连续寄存器内容的!没有这一句会导致下一次的IIC读取时序与PCF的时序不同而产生异常!!!这一注意事项其实在IIC的介绍中已经强调过!

http://www.xdnf.cn/news/13196.html

相关文章:

  • 2025 高考:AI 都在哪些地方发挥了作用
  • 行为设计模式之Memento(备忘录)
  • 守护数字世界:网络安全核心技术与实践策略
  • VSCODE配置ESP-IDF芯片选择遇见的问题
  • 赛尔发布SHARE 5系列航测相机,外业更高效,建模更优质
  • 代码随想录刷题day31
  • 从基础到实战-rmpt to webrtc
  • WiFi通信应用开发【保姆级】实现ESP8266模块数据上传到云端!!!
  • matlab 各种智能优化算法
  • 26考研 专业课 百度网盘夸克网盘
  • C++_红黑树
  • Easy系列PLC变频器控制功能块(ST源代码)
  • 积累-Vue.js 开发实用指南:ElementUI 与核心技巧
  • AI驱动下的商品详情API:2025年电商平台的智能化数据交互新趋势
  • Qt5 框架 CMake 探秘
  • 编译原理 学习 2025年6月10日11:17:54
  • 笔记——学习HTTP协议
  • 第二篇:Agent2Agent (A2A) 协议——A2A 架构、组件和通信动态
  • 百度之星2021——BD202104 萌新
  • JavaScript闭包-作用域链的魔法
  • KubeSphere 容器平台高可用:环境搭建与可视化操作指南
  • YOLO电力物目标检测训练
  • Spring Boot + Vue 前后端分离项目解决跨域问题详解
  • HTML 语义化
  • ​​CentOS 7.9​​ 上配置 ​​Fail2ban 自动封禁 IP​​ 的完整步骤,整合了多篇权威资料的最佳实践
  • 功能界面的组件化编码流程
  • LeetCode 11题“盛最多水的容器”
  • 论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(三)
  • SecureCRT 中使用 `crt.Session.Config.SetOption` 方法
  • STM32时钟与GPIO工作模式