【学习】PCF8563芯片资料和相关功能解析

【学习】PCF8563芯片资料和相关功能解析


PCF8563芯片是以I2C通讯方式的实时时钟/日历芯片。它提供一个可编程时钟输出,一个中断输出和掉电检测器,所有的地址和数据通过 I2C 总线接口串行传递。最大总线速度为400Kbits/s”每次读写数据后,内嵌的字地址寄存器会自动产生增量。

功能描述

  • PCF8563 有 16 个8位寄存器:一个可自动增量的地址寄存器,一个内置 32.768KHz 的
    振荡器(带有一个内部集成的电容),一个分频器(用于给实时时钟 RTC 提供源时钟)一
    个可编程时钟输出,一个定时器,一个报警器,一个掉电检测器和一个 400KHz I2C 总线接口。

  • 所有 16 个寄存器设计成可寻址的 8 位并行寄存器,但不是所有位都有用。前两个寄存器(内存地址 00H,01H)用于控制寄存器和状态寄存器,内存地址 02H~08H 用于时钟计数器(秒~年计数器),地址 09H~0CH 用于报警寄存器(定义报警条件),地址 0DH 控制CLKOUT 管脚的输出频率,地址 0EH 和 0FH 分别用于定时器控制寄存器和定时器寄存器。秒、分钟、小时、日、月、年、分钟报警、小时报警、日报警寄存器,编码格式为 BCD,星期和星期报警寄存器不以 BCD 格式编码。当一个 RTC 寄存器被读时,所有计数器的内容被锁存,因此,在传送条件下, 可以禁止对时钟/日历芯片的错读。

  • 报警功能模式

一个或多个报警寄存器 MSB(AE=Alarm Enable 报警使能位)清0时,相应的报警条件有效,这样,一个报警将在每分钟至每星期范围内产生一次。设置报警标志位 AF(控制/状态寄存器2的位3)用于产生中断,AF 只可以用软件清除。

  • 定时器

8位的倒计数器(地址 0FH)由定时器控制寄存器(地址 0EH,参见表 25)控制,定时器控制寄存器用于设定定时器的频率(4096,64,1,或 1/60Hz),以及设定定时器有效或无效。定时器从软件设置的 8 位二进制数倒计数,每次倒计数结束,定时器设置标志位TF(参见表7),定时器标志位 TF 只可以用软件清除,TF 用于产生一个中断(/INT),每个倒计数周期产生一个脉冲作为中断信号。TI/TP(参见表 7)控制中断产生的条件。当读定时器时,返回当前倒计数的数值。

  • CLKOUT 输出

管脚 CLKOUT 可以输出可编程的方波。CLKOUT 频率寄存器(地址 0DH;参见表 23)决定方波的频率,CLKOUT 可以输出 32.768KHz( 缺省值),1024,32,1Hz 的方波。CLKOUT为开漏输出管脚,通电时有效,无效时为高阻抗。

  • 复位

PCF8563 包含一个片内复位电路,当振荡器停止工作时,复位电路开始工作。在复位状态下,I2C 总线初始化,寄存器 TF、VL、TD1、TD0、TESTC、AE 被置逻辑1,其它的寄存器和地址指针被清0。

寄存器结构

  • 标明“一”的位无效,标明“0”的位应置逻辑0。
    在这里插入图片描述
  • BCD 格式寄存器概况(标明“-”的位无效 )
    在这里插入图片描述

连续读取函数

void ReadData1(unsigned char address,unsigned char count,unsigned char * buff) /*多字节*/
{
    
    
    unsigned char i;
    iic_start(); /*开始信号*/
    iic_send_byte(0xa2); /*写命令*/
    iic_ack();/*应答信号拉低,表示接收成功,Proteus仿真时必须要有这个信号*/
    iic_send_byte(address); /*写地址*/
    iic_ack();/*应答*/
    iic_start();/*开始信号*/
    iic_send_byte(0xa3); /*读命令*/
    iic_ack();/*应答*/
    for(i=0; i<count; i++)
    {
    
    /*连续读取7个byte数据,也就是秒-分-时-日期-周-月份-年*/
        buff[i]=Readbyte();
        if(i<count-1)
            WriteACK(0);
    }
    WriteACK(1);
    iic_stop();
}
  • 秒、分钟和小时寄存器
    在这里插入图片描述
  1. 秒时间读取代码
sec = 0x7f&read_buff[0];//秒
  1. 分时间读取代码
  min = 0x7f&read_buff[1] ;
  1. 小时时间读取代码
hour   = 0x3f&read_buff[2];
  1. 天读取代码
  day   = 0x3f&read_buff[3];//日期
  1. 星期读取代码
 week = 0x07&read_buff[4];//周不需要BCD转码
  1. 月份读取代码
mon   = 0x1f&read_buff[5];//月份
  1. 年份读取代码
year   = 0xff&read_buff[6] ;

以上读取的都是BCD码值,还需要进行数据转换。除了周以外

BCD转10进制方法

//----------------BCD转10进制-----------
uchar bcd_dec(uchar bat)
{
    
    
    return ( (bat/16*10) + (bat%16) );
}

/****或****/
//----------------BCD转10进制-----------
uchar bcd_dec(uchar bat)
{
    
    
    uchar temp1,temp2,tol;
   temp1=bat&0x0f;
   temp2=(bat&0xf0)>>4;
    tol=temp2*10+temp1;
    return tol;
}

I2C通讯相关内容

  • 开始信号

开始信号:SCL为高期间, SDA由高到低的跳变;(特别注意:启动信号是一种电平跳变时序信号,下面是程序编写)

void IIC_Start(void)
{
    
    
    SDA_OUT();     	/*设置C12为输出模式*/
	IIC_SDA=1;	  	/*拉高保持空闲状态*/  
	IIC_SCL=1;		/*拉高保持空闲状态*/  
	delay_us(4);    /*延时保证电平稳定*/  
 	IIC_SDA=0;   	/*当SCL为高时,SDA由高到低的跳变*/  
	delay_us(4);    /*延时保证电平稳定*/ 
	IIC_SCL=0;		/*钳住I2C总线,准备发送或接收数据*/
}	

  • 停止信号
void IIC_Start(void)
{
    
    
    SDA_OUT();     	/*设置C12为输出模式*/
	IIC_SDA=1;	  	/*拉高保持空闲状态*/  
	IIC_SCL=1;		/*拉高保持空闲状态*/  
	delay_us(4);    /*延时保证电平稳定*/  
 	IIC_SDA=0;   	/*当SCL为高时,SDA由高到低的跳变*/  
	delay_us(4);    /*延时保证电平稳定*/ 
	IIC_SCL=0;		/*钳住I2C总线,准备发送或接收数据*/
}	

  • 应答信号(单片机读取PCF8563里的数据。故此处发送器为PCF8563,接收器为单片机。)

发送器(PCF8563读数据时)每发送一个字节, 就在时钟脉冲第9个期间释放数据线,由接收器(单片机)反馈一个应答信号。
当应答信号为低电平时, 表示接收器已经成功地接收了该字节,规定为应答位(ACK)
当应答信号为高电平时, 表示接收器接收该字节失败。规定为非应答位(NACK)

  • 对于反馈有效应答位ACK的要求是,接收器在第9个时钟脉冲之前的低电平期间将SDA线拉低, 并且确保在该时钟的高电平期间为稳定的低电平。

同时我们还需要对应答信号进行判断,所以我们此处需要编写三个程序:1、产生应答信号;2、产生非应答信号;3、检测应答信号,其中产生应答信号和产生非应答信号是接收器(单片机)使用的,检测应答信号为发送器(PCF8563)使用的。

  1. 产生应答信号
void IIC_Ack(void)
{
    
    
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}

  1. 产生非应答信号
void IIC_NAck(void)
{
    
    
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}	

  1. 检测应答信号
u8 IIC_Wait_Ack(void)
{
    
    
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
    
    
		ucErrTime++;
		if(ucErrTime>250)
		{
    
    
			IIC_Stop();
			return 1;/*数据传送失败。检测为非应答信号*/
		}
	}
	IIC_SCL=0;//时钟输出0 	   
	return 0;  /*数据传送失败。检测为应答信号*/
} 

读1byte数据

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
    
    
	unsigned char i,receive=0;
	SDA_IN();/*SDA设置为输入*/
    for(i=0;i<8;i++ )
	{
    
    
        IIC_SCL=0; 
        delay_us(2);
		IIC_SCL=1;
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();/*发送NACK*/
    else
        IIC_Ack(); /*发送ACK*/
    return receive;
}

写1byte数据

//IIC发送一个字节//返回从机有无应答//1,有应答//0,无应答	
void IIC_Send_Byte(u8 txd)
{
    
                            
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;/*拉低时钟开始数据传输*/
    for(t=0;t<8;t++)
    {
    
                  
        IIC_SDA=(txd&0x80)>>7;/*需要发送的数据经过和0x80的与运算之后,右移7位*/
        txd<<=1;/*左移7位*/
		delay_us(2);   /*对延时是必须的*/
		IIC_SCL=1;
		delay_us(2);  /*对延时是必须的*/
		IIC_SCL=0;	
		delay_us(2); /*对延时是必须的*/
    }	 
} 

在使用Proteus仿真PCF8563时需要添加相关的应答信号,否则读的数据就会不断的跳动,如果是实际硬件电路搭建的话可以忽略这一点。

おすすめ

転載: blog.csdn.net/weixin_42880082/article/details/122321319