标题：pcf8563
基本信息
外围器件PCF8563I2C实时时钟/日历芯片
在8051系统中的应用
摘要：文中介绍了PCF8563的结构、功能及工作原理。结合其在8051系统中的应用实例，给出了PCF8563与8051单片机的硬件接口电路和C语言软件编程程序。
关键词：I2C总线 串行接口 PCF8563 BCD码 C语言
PCF8563简介：PCF8563是PHILIPS公司生产的低功耗CMOS实时时钟/日历芯片，芯片最大总线速度为400kbits/s，每次读写数据后，其内嵌的字地址寄存器器会自动产生增量。PCF8563可广泛应用于移动电话、便携仪器、传真机、电池电源等产品中。
PCF8563的引脚排列如图1所示，各引脚功能说明如表1所列。
PCF8563有16个8位寄存器，其中包括：可自动增量的地址寄存器、内置32.768kHz的振荡器（带有一个内部集成电容）、分频器（用于给实时时钟RTC提供源时钟）、可编程时钟输出、定时器、报警器、掉电检测器和400kHz的I2C总线接口。所有16个寄存器设计成可寻址的8位并行寄存器，但不是所有位都有用。当一个RTC寄存器被读时，所有计数器的内容将被锁存，因此，在传送条件下，可以禁止对时钟/日历芯片的错读。表2、表3所列为各寄存器概况及对应的内存地址和功能，同时列出了它们的BCD格式编码。表中“——”表示无效位，“0”表示此位应置逻辑。表3中的世纪位C=0指定世纪数为20XX，C=1指定世纪数为19XX。当年寄存器中的99变00时，世纪位才会改变。
其主要特性有： 
1、宽电压范围 1.0~5.5V， 复位电压标准值Vlow=0.9V。 
2、超低功耗：典型值为 0.25uA (VDD=3.0V,Tamb=25℃)。 
3、可编程时钟输出频率为：32.768KHz 、1024Hz 、32Hz 、1Hz。 
4、四种报警功能和定时器功能。 
5、内含复位电路、振荡器电容和掉电检测电路。 
6、开漏中断输出。 
7、400kHz I2C总线(VDD=1.8~5.5V)，其从地址读 0A3H;写 0A2H。
管脚描述
  PCF8563 管脚图符号管脚号描 述 OSCI1振荡器输入OSCO 2振荡器输出 /INT 3中断输出（开漏：低电平有效）VSS4地 SDA5串行数据 I/O SCL 6串行时钟输入CLKOUT 7时钟输出（开漏）VDD8正电源 
基本工作原理
PCF8563 有 16 个位寄存器：一个可自动增量的地址寄存器，一个内置 32.768KHz的振荡器（带有一个内部集成的电容）一个分频器（用于给实时时钟RTC 提供源时钟）一个可编程时钟输出，一个定时器，一个报警器，一个掉电检测器和一个 400KHz I2C 总线接口。 
所有16 个寄存器设计成可寻址的 8 位并行寄存器，但不是所有位都有用。前两个寄存器（内存地址 00H，01H）用于控制寄存器和状态寄存器，内存地址 02H~08H 用于时钟计数器（秒~年计数器） ，地址 09H~0CH 用于报警寄存器（定义报警条件） ，地址 0DH 控制CLKOUT 管脚的输出频率，地址 0EH 和 0FH 分别用于定时器控制寄存器和定时器寄存器。秒、分钟、小时、日、月、年、分钟报警、小时报警、日报警寄存器，编码格式为 BCD， 星期和星期报警寄存器不以 BCD 格式编码。当一个 RTC 寄存器被读时，所有计数器的内容被锁存，因此，在传送条件下，可以禁止对时钟日历芯片的错读。
寄存器概况
地址 寄存器名称 Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0 00H 控制/状态寄存器1 TEST 0 STOP 0 TESTC 0 0 0 01H 控制/状态寄存器2 0 0 0 TI/TP AF TF AIE TIE 0DH CLKOUT频率寄存器 FE — — — — — FD1 FD0 0EH 定时器控制寄存器 TE — — — — — TD1 TD0 0FH 定时器倒计数数值寄存器 定时器倒计数数值
BCD格式寄存器概况
1. 地址寄存器名称 Bit7 Bit6 Bit5 Bit4 Bit3 Bit2 Bit1 Bit0。 
02H 秒：VL 00～59BCD码格式数
03H 分：00～59BCD码格式数
04H 时：00～23BCD码格式数 
05H 日：01～31BCD码格式数
06H 星期：0～6 
07H 月/世纪：C - - 01～12BCD码格式数 
08H 年：00～99BCD码格式数 
09H分钟报警：AE - 00～59BCD码格式数 
0AH小时报警：AE - 00～23BCD码格式数 
0BH 日报警： AE -01～31BCD码格式数 
0CH 星期报警：AE - 0～6 
2.开始和停止
STOP和START状态之间总线空置，数据线（SDA）和时钟线（SCL）保持在高电平。SCL高电平时SDA下降沿，为启动条件（S）；SCL高电平时SDA上升沿为停止条件（P），参见下图。
  开始和停止定义
3. 位传送 
每个时钟脉冲传送一个数据位，SDA线上的数据在时钟脉冲高电平时应保持稳定，否则将成为控制信号，参见图4。
4.标志位
在START和STOP之间，发射器发送给接收器的数据数量没有限制。在每个8位字节后加一个标志位，发射器便产生一个高电平的标志位，这时主设备产生一个附加标志位时钟脉冲。
“从接收器”必须在接收到每个字节后产生一个标志位，“主接收器”也必须在接收“从发射器”传送的每个字节后产生一个标志位。
在标志位时钟脉冲出现时，SDA线应保持低电平（应考虑起动和保持时间）。
发射器应在从设备接收到最后一个字节时变为低电平，而使接收器产生标志位，这时主设备即可产生停止条件。参见图5。
5. I2C总线协议 
用I2C总线传递数据前，接收的设备应先标明地址，在I2C总线起动后，这个地址与第一个传送字节一起被传送出去。PCF8563可以作为一个从接收器或从传送器，此时的时钟信号线SCL只能输入信号线，数据信号线SDA则为一条双向信号线。PCF8563的从地址参见图6。
应用概述
图7所示为PCF8563的具体应用电路图，对图中石英晶片频率的调整，笔者给出3种可行性方法，供参考： 方法1：定值OSCI电容。计算所需的电容平均值，用此值的定值电容，通电后在CLKOUT管脚上测出的频率应为32.768kHz，测出的频率值偏差取决于石英晶片本身，电容偏差和器件之间的偏差平均为±5×10 -6。平均偏差可达5分钟/年。 方法2：OSCI微调电容。可通过调整OSCI管脚的微调电容式振荡器的频率来获得更高的精度，此时可测出通电时管脚CLKOUT上的信号频率为32.768kHz。 方法3：OSCI输出。直接测量管脚OSCI的输出。
程序范例
以下的C语言源程序是用8051单片机的普通I/O口（如P0.0/P0.4）模拟实现PCF8563的I2C时钟/日历芯片的操作，有字节写/读两种状态。程序中从地址的读地址为0A3H，写地址为0A2H.所发送的数据字节为9个，发送的初始数据在rom_sed[9]中，rom_sed[9]定义了寄存器中当前发送的值：控制/状态寄存器1为0，控制/状态寄存器2为0，秒寄存器为0，分钟寄存器55，小时寄存器为23，日寄存器为31，星期寄存器为6，月/世纪寄存器为0x12，年寄存器为0x99（即1999年12月31日23点55分0秒），当程序运行一段时间（5分钟）后，从地址寄存器02H开始读数据，数据存放在rom_rec7中，发现变量rom_rec7变为2000年1月1日0点0分。若外转帐电路有显示，则时间可以显示在面板上。 #include<d:.h> #define byte unsignedchar sbit scl=0x81; //定义串行I/O口 sbit sda=0x80; idata byte rom_sed[9];idata byte rom_rec[7]; idata byte j,k; bit flag,flag1; void delay(void)//延时子程序 {data byte i; for(i=0;i<6;i++); } void I_start(void)//发送I2C总线起始条件子程序 {sda=1; ; scl=1; delay(); sda=0; delay(); scl=0; ; }void I_stop(void) //I2C总线停止条件子程序 {sda=0; ; scl=1; delay(); sda=1;delay(); } bit I_send(byte I_data) //字节数据传送子程序 {data byte i;for(i=0,i<8;i++) {sda-(bit)(I_data&0x80);I_data=I_data<<1; ; scl=1; delay(); scl=0; } ;; sda=1; ;; //readyfor receiving ACK bit scl=1; ;; //start receiving ack bit flag=0;if(sda= =0)flag=0; else flag=1; //return(～I_clock()); scl=0;return(flag); } byte I_receive(void) //字节数据接收子程序 { data byte i; byteI_data=0; sda=1; for(i=0;I<8;i++) { I_data*=2; ; scl=0; delay();scl=1; ;; if(sda= =1)I_data++; ;; } scl=0; ;;; sda=0; if(flag1==0){;;scl=1;delay();scl=0;} //not last receic_byte ACK else{sda=1;;;scl=1;delay();scl=0;flag1=0;} //the last receive_byte ～ACKreturn(I_data); } main() //主程序 {data byte i; rom_sed[0]=0x00;rom_sed[1]=0x00; rom_sed[2]=0x00; rom_sed[3]=0x55; rom_sed[4]=0x23;rom_sed[5]=0x31; rom_sed[6]=0x06; rom_sed[7]=0x92; rom_sed[8]=0x99;for(i=0;i<255;i++)delay(); I_start(); if(～I_send(rom_sed[i])); else;} I_stop(); } else; } else; start: I_start(); if(～I_send(0xa2))//pcf_write address {if(～I_send(0x02)) //pcf_status register address{I_start(); if(～I_send(0xa3)) //write status register{for(i=0;i<7;i++) {if(i= =6)flag1=1; else flag1=0;rom_rec[i]=I_receive(); switch(i) {case1:rom_rec[i]=rom_rec[i]&0x7f;break; ease2:case3:rom_rec[i]=rom_rec[i]&0x3f;break;case4:rom_rec[i]=rom_rec[i]&0x07;break;case5:rom_rec[i]=rom_rec[i]&0x9f;brealk;default:break; } } I_stop()} } } goto start; }