pcf8563.c
来自「stc15单片机测试程序V1.0版」· C语言 代码 · 共 257 行
C
257 行
#include "STC15F2K.h"
#include <intrins.H>
#define uchar unsigned char
#define uint unsigned int
sbit scl=P1^6;
sbit sda=P1^7;
/*----------------------------------------------------------------------------&
I2C程序
----------------------------------------------------------------------------&&*/
void delay_() //2us
{
unsigned char i;
i = 3;
while (--i);
}
void start()//IIC启动
{
sda=1;
delay_();
scl=1;
delay_();
sda=0;
delay_();
scl=0; //可以尝试屏蔽scl=0;
delay_();
}
void stop() //IIC结束
{
sda=0;
delay_();
scl=1;
delay_();
sda=1;
delay_();
scl=0; //可以尝试屏蔽scl=0;
delay_();
}
/*******************************************************************************
功能描述:主机应答
注:主设备(比如单片机),从 从设备(比如PCF8563)读取字节后,如果
要继续读取,就要给从设备一个ACK(即所谓的”应答“,数据位SDA为0)
*******************************************************************************/
void ack()
{ uchar i;
sda=0;
delay_();
scl=1; //在时钟线为高电平的情况下,数据线上的值(SDA=0)被写入到从机中
delay_();
while((sda==1)&&(i<250))i++;
scl=0;
delay_();
}
/*******************************************************************************
功能描述:主机无应答
注:主设备(比如单片机),从 从设备(比如PCF8563)读取字节后,如果不再
进行读取,就要给从设备一个NACK(即所谓的”无应答“,数据位SDA为1)
*******************************************************************************/
void nack()
{ uchar i;
sda=1;
delay_();
scl=1; //在时钟线为高电平的情况下,数据线上的值被写入到从机中
while((sda==0)&&(i<250))i++;
delay_();
scl=0;
delay_();
}
/*******************************************************************************
功能描述:主设备检测从设备应答
返回说明:从设备的应答值
注:主设备向从设备写入字节后,要检测从设备发出的应答,
如果数据位SDA为0,说明向从设备成功写入了字节。1写入失败
*******************************************************************************/
uchar getack() //从机应答
{
uchar error;
sda=1; //为了后面能对数据线上的状态进行读取,51中要将IO
delay_(); //当做输入时,必须置为高电平
scl=1; //时钟为高时,从机发出应答信号
delay_();
error=sda; //对数据线上的状态进行读取并赋值给Error
delay_();
scl=0;
delay_();
return error;
}
/*******************************************************************************
功能描述:主设备向从设备写入一字节
参数说明:dat:将要写入的字节
返回说明:从设备的应答值
注:向从设备写入一个字节,并返回从设备的应答值
*******************************************************************************/
uchar writebyte(uchar dat)
{
uchar i;
for(i=0;i<8;i++)
{
sda=((dat<<i)&0x80);//先写字节的高位,赋值给数据线
scl=1; //SCL高电平时,数据线上的数据有效,被写入到从机中
delay_();
scl=0;
delay_();
}
return getack();//返回从机应答
}
/*******************************************************************************
功能描述:主设备从从设备读取一字节
返回说明:读到的字节
*******************************************************************************/
uchar readbyte()
{
uchar i,rbyte=0;
scl=0;
delay_();
sda=1; //为了后面能对数据线上的状态进行读取
delay_();
for(i=0;i<8;i++)
{
scl=1; //在时钟线为高的情况下,从机在数据线上输出相应的位
delay_();
rbyte=(rbyte<<1)|sda;
scl=0;
delay_();
}
return rbyte; //读到的字节
}
/*----------------------------------------------------------------------------&
pcf8563
----------------------------------------------------------------------------&&*/
struct Time //时间结构体,包括了秒,分,时,日,周,月,年
{
uchar second;
uchar minute;
uchar hour;
uchar day;
uchar week;
uchar month;
uchar year;
};
struct Time time; //用来装时间数据
/*******************************************************************************
功能描述:向地址addr的寄存器写入多个字节
参数说明:addr:寄存器地址
length:要写入的字节数
pbuf:指向数据缓冲区的指针
返回说明:操作结果,0表示成功,1表示失败
*******************************************************************************/
uchar pcfwrite(uchar addr,uchar length,uchar *pbuf )
{
uchar i=0;
start();
if(writebyte(0xa2)) return 1; /*写pcf8563的ID与读控制位,通信有错误返回
IIC写入一个字节以后,将会读取从机上的应答,如果为0说明写入成功,如果为1则写入失败,
这里判断写入字节后的返回值,为1则返回1,即(这个函数运行失败),否则继续向下运行*/
if(writebyte(addr)) return 1; //写寄存器地址
for(i=0;i<length;i++) //写入length个字节
{
if(writebyte(pbuf[i])) return 1;//写数据
}
stop();
return 0;
}
/*******************************************************************************
功能描述:从地址addr的寄存器读取多个字节
参数说明:addr:寄存器地址
length:要读出的字节数
pbuf:指向数据缓冲区的指针
返回说明:操作结果,0表示成功,1表示失败
*******************************************************************************/
uchar pcfread(uchar addr,uchar length,uchar *pbuf)
{
uchar i=0;
start();//通信开始
if(writebyte(0xa2)) return 1;//写PCF8563的ID与读(写)控制位,通信有错误返回
if(writebyte(addr)) return 1;//写寄存器地址
start();//通信开始
if(writebyte(0xa3)) return 1;//写PCF8563的ID与(读)写控制位,通信有错误返回
for(i=0;i<length-1;i++) //写入前length-1个字节,并作出应答
{
pbuf[i]=readbyte();
ack(); //每读取一个字节,主机应答
}
pbuf[i]=readbyte(); //写入最后一个字节且不应答
nack();
stop();
return 0;
}
/*******************************************************************************
功能描述:将BCD码转换为十进制的数值
参数说明:x:待转换的BCD码字节
返回说明:转换后的值
注:将BCD格式数据转为实际的值,如29的BCD格式为0x29,实
*******************************************************************************/
uchar bcdval(uchar x)
{return (x>>4)*10+(x&0x0f);//bcd码转为十进制
} //高四位乘以十加上低四位
/*******************************************************************************
功能描述:将十进制的数值转换为BCD码
参数说明:x:待转换的BCD码字节
返回说明:转换后的值
注:将BCD格式数据转为实际的值,如29的BCD格式为0x29,实
*******************************************************************************/
uchar valbcd(uchar x) //十进制数转为BCD码
{return (x/10)*16+(x%10);//十位乘以16加上个位
}
/*******************************************************************************
功能描述:读取时间
返回结果:操作结果,0表示成功,1表示失败
注:从PCF8563中读到的时间值,被装载到全局的外部结构体
*******************************************************************************/
uchar readtime()
{
uchar temp[7];//用于装载读回来的秒-年的7个字节的数据
if(!pcfread(0x02,7,temp))/*读取时间;时间寄存器的地址是02,
从02这个地址中读取7个字节放到temp中*/
{
//以下对读取到temp数组中的时间数据进行截取
//并转换为十进制写入到time中去
time.second=bcdval(temp[0]&0x7f);//秒,通过与操作屏蔽多余的位
time.minute=bcdval(temp[1]&0x7f);//分,获取真正的时间
time.hour =bcdval(temp[2]&0x3f);//时,bcd--是将bad编码转换成十进制数的函数
time.day =bcdval(temp[3]&0x3f);//日
time.week =bcdval(temp[4]&0x07);//星期
time.month =bcdval(temp[5]&0x1f);//月
time.year =bcdval(temp[6] );//年
return 0;//返回0,运行成功
}
else return 1;
}
/*******************************************************************************
功能描述:设置时间
返回结果:操作结果,0表示成功,1表示失败
注:在设置时间前先将事间数据填充到time中去,随后调用此函数,时间
数据即被写入到PCF8563中,并以新设置的时间继续走时
*******************************************************************************/
uchar settime()
{
uchar i,temp[7];
for(i=0;i<7;i++)
{
temp[i]=valbcd(((uchar *)(&time))[i]);//将time中的十进制时间数据转换为BCD
} //转换后装到temp[7]临时数组中
return pcfwrite(0x02,7,temp);//将temp数组的数据写入到时间寄存器中
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?