文章目录[隐藏]
【学习】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();
}
- 秒、分钟和小时寄存器
- 秒时间读取代码
sec = 0x7f&read_buff[0];//秒
- 分时间读取代码
min = 0x7f&read_buff[1] ;
- 小时时间读取代码
hour = 0x3f&read_buff[2];
- 天读取代码
day = 0x3f&read_buff[3];//日期
- 星期读取代码
week = 0x07&read_buff[4];//周不需要BCD转码
- 月份读取代码
mon = 0x1f&read_buff[5];//月份
- 年份读取代码
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)使用的。
- 产生应答信号
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
- 产生非应答信号
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
- 检测应答信号
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时需要添加相关的应答信号,否则读的数据就会不断的跳动,如果是实际硬件电路搭建的话可以忽略这一点。
- I2C相关内容请看《常用通信协议——IIC协议编程实现》
版权声明:本文为CSDN博主「perseverance52」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42880082/article/details/122321319
【学习】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();
}
- 秒、分钟和小时寄存器
- 秒时间读取代码
sec = 0x7f&read_buff[0];//秒
- 分时间读取代码
min = 0x7f&read_buff[1] ;
- 小时时间读取代码
hour = 0x3f&read_buff[2];
- 天读取代码
day = 0x3f&read_buff[3];//日期
- 星期读取代码
week = 0x07&read_buff[4];//周不需要BCD转码
- 月份读取代码
mon = 0x1f&read_buff[5];//月份
- 年份读取代码
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)使用的。
- 产生应答信号
void IIC_Ack(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=0;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
- 产生非应答信号
void IIC_NAck(void)
{
IIC_SCL=0;
SDA_OUT();
IIC_SDA=1;
delay_us(2);
IIC_SCL=1;
delay_us(2);
IIC_SCL=0;
}
- 检测应答信号
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时需要添加相关的应答信号,否则读的数据就会不断的跳动,如果是实际硬件电路搭建的话可以忽略这一点。
- I2C相关内容请看《常用通信协议——IIC协议编程实现》
版权声明:本文为CSDN博主「perseverance52」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42880082/article/details/122321319
暂无评论