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 + -
显示快捷键?