⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcf8563.c

📁 你还在自己模拟IIC总线时序吗?别傻啦
💻 C
字号:
//-------------------------------------------------------------------
// rtc.c
// 功能:实现对PCF8563的读取,用于C8051F020中,使用C8051F020的SMBus功能
//      使用查询方式读取和写入数据
// 说明:本例程中对SMBus的操作使用的是查询的方式进行的,还可以采用中断的方式
//       可以参考其它相关的例程
// 版本: Rev1.0
// 
//------------------------------------------------------------------
// 修改记录
// 版本        时间          人员            内容
// 1.0        07/05/03       scj            移植程序
//
//
//------------------------------------------------------------------

#include "rtc.h"
#include "F020.h"


BYTE code MYHTAB[]="0123456789ABCDEF";

//..................................................................
// 全局变量定义
//..................................................................

xdata BYTE CurrentTime[8];              // 实时时钟时间
xdata char CurrentTimeString[17];       // 当前时间的字符串形式

extern void Dlyms(WORD ms);

	
//----------------------------------------------------------------------
// 功能描述:从某一地址连续读n个字节
// 其中:n 的低4位(B3B2B1B0)为长度(0表示16)
// 过程:写器件地址,读寄存器内容    
//----------------------------------------------------------------------
void I2RD(BYTE addr,BYTE *pBuf,BYTE n)	// 从某一地址连续读n个字节
{
	BYTE i;								// 循环变量
	BYTE slave;							// 器件和页地址
	BYTE datu;
										// 计算地址
											
	// 计算长度
	n&=0x0F;							// n=长度
	if(n==0) n=16;						// n=0 表示16字节
	
	/////////////////////////////////////////////////////////////////////
	// 首先写寄存器地址
	slave=DEVICE_WADD;					// 求器件地址(0110 c2c1c0 1)
	
	SI=0;								
	STO=0;
	STA=1;								// 发送起始条件
	while(!SI) {}						// 等待起始条件发送
	datu=SMB0STA;
	STA=0;								// 清零起始条件
			
	SMB0DAT=slave;						// 发送器件地址
	SI=0;
	while(!SI) {}						// 等待器件地址发送完毕
	datu=SMB0STA;
			
	SMB0DAT=addr;						// 发送寄存器地址
	SI=0;
	while(!SI) {}						// 等待寄存器地址发送完毕
	datu=SMB0STA;
	
	//////////////////////////////////////////////////////////////////////	
	// 发送读命令
	slave = DEVICE_RADD;
										
	STO=0;
	STA=1;								// 发送起始条件
	SI=0;
	while(!SI) {}						// 等待起始条件发送
	datu=SMB0STA;
	STA=0;								// 清零起始条件
			
	SMB0DAT=slave;						// 发送器件地址
	SI=0;
	while(!SI) {}						// 等待器件地址发送完毕
	datu=SMB0STA;
	
	////////////////////////////////////////////////////////////////////
	// 读数据
		
	for(i=0;i<n-1;i++){
		AA=1;							// 收到字节后发送ACK
		SI=0;
		while(!SI) {}
		datu=SMB0STA;
		datu=SMB0DAT;
		pBuf[i]=datu;
	}
	
	AA=0;								// 最后一个字节,发送NACK
	SI=0;
	
	while(!SI) {}
	
	datu=SMB0STA;
		
	datu=SMB0DAT;
	pBuf[i]=datu;						// 读出最后一个字节
	
	///////////////////////////////////////////////////////////////////
	// 发送停止
	SI=0;
	STO=1;								// 置位停止条件
	while(!SI) {}
	SI=0;
		
	return;								// 返回
}
//----------------------------------------------------------------------
// 功能:向某一个地址写入数据
// 其中:n表示长度
//----------------------------------------------------------------------
void I2WR(BYTE addr,BYTE *pBuf,BYTE n)	// 向某一地址连续写n个字节
{										// 
	BYTE i;								// 循环变量
	BYTE slave;							// SLAVE地址
	BYTE datu;

	slave=DEVICE_WADD;					// 求器件地址(0110 c2c1c0 0)
		
	n&=0x0F;							// n=长度
	if(n==0) n=16;						// n=0 表示16字节
	
	SI=0;  
	STO=0;								
	STA=1;								// 发送起始条件
	
	while(!SI) {}						// 等待发送条件结束 
	datu=SMB0STA;						// 数据状态
	STA=0;								// 发送条件结束
	
	SMB0DAT=slave;						// 发送器件地址
	SI=0;								// 恢复为高电平SCL
	while(!SI) {}						// 等待发送完毕
	datu=SMB0STA;						// 数据状态
	
	SMB0DAT=slave;						// 发送寄存器地址
	SI=0;								// 恢复为高电平SCL
	
	for(i=0;i<n;i++){					// 开始读取数据

		while(!SI) {}					// 等待发送完毕
		datu=SMB0STA;					// 数据状态
		
		datu=pBuf[i];
		SMB0DAT=datu;                   // 发送数据字节
		SI=0;
	}
			
	while(!SI) {}                       // 最后一个字节发送完毕
		
	STO=1;								// 结束条件
	SI=0;
//	while(!SI) {}
	datu=SMB0STA;
//	SI=0;
		
	Dlyms(10);							// 延时
	return;								// 返回
}

//.................................................................
// 功能: 从PCF8563T中读取当前时间,并返回时间字符串的指针
// 输入参数:无
// 输出参数: char *:指向时间字符串存储指针,外部函数不允许修改该缓冲区内容
//.................................................................
const char *GetNowTime()
{
	// 从PCF8563中读出当前时间
	I2RD(REG_SECD,CurrentTime,8);
		
	CurrentTimeString[0]=MYHTAB[(CurrentTime[RTC_HOUR]>>4)&0x03];
	CurrentTimeString[1]=MYHTAB[CurrentTime[RTC_HOUR]&0x0F];
		
	CurrentTimeString[2]=':';
	CurrentTimeString[3]=MYHTAB[(CurrentTime[RTC_MINU]>>4)&0x07];
	CurrentTimeString[4]=MYHTAB[CurrentTime[RTC_MINU]&0x0F];
	
	CurrentTimeString[5]=0x20;
	// 年
	CurrentTimeString[6]=(CurrentTime[RTC_MON]&0x80)?MYHTAB[1]:MYHTAB[2];
	CurrentTimeString[7]=(CurrentTime[RTC_MON]&0x80)?MYHTAB[9]:MYHTAB[0];   
	CurrentTimeString[8]=MYHTAB[(CurrentTime[RTC_YEAR]>>4)&0x0F];
	CurrentTimeString[9]=MYHTAB[CurrentTime[RTC_YEAR]&0x0F];
	// 月
	CurrentTimeString[10]='/';
	CurrentTimeString[11]=MYHTAB[(CurrentTime[RTC_MON]>>4)&0x01];
	CurrentTimeString[12]=MYHTAB[CurrentTime[RTC_MON]&0x0F];
	// 日
	CurrentTimeString[13]='/';
	CurrentTimeString[14]=MYHTAB[(CurrentTime[RTC_DAY]>>4)&0x03];
	CurrentTimeString[15]=MYHTAB[CurrentTime[RTC_DAY]&0x0F];
	
	CurrentTimeString[16]=0;
	
	return &CurrentTimeString[0];
}

// 设置当前时间
// 年/月/日/周/小时/分/秒
void SetNowTime(BYTE y2k,BYTE year,BYTE month,BYTE day,BYTE hour,BYTE min,BYTE sec)
{
	BYTE datu;
		
	CurrentTime[RTC_DW]   = 0x00;
	CurrentTime[RTC_YEAR] = year;
	CurrentTime[RTC_MON]  = (y2k==0x19)?month|0x80:month&0x7F;
	CurrentTime[RTC_DAY]  = day;
	CurrentTime[RTC_HOUR] = hour|0x80;
	CurrentTime[RTC_MINU] = min;
	CurrentTime[RTC_SECD] = (sec>0x59)?0x59:sec;
	
	
	// 设置当前时间
	I2WR(REG_SECD,CurrentTime,7);
}

/*
// 设置当前秒
void SetCurrentSec(BYTE sec)
{
	CurrentTime[RTC_SECD]= sec;
	
	I2WR(REG_SC,&CurrentTime[RTC_SECD],1);
}
*/

// 检测时钟芯片是否从掉电状态启动
bit IsFromFail()
{
	BYTE datu;

	I2RD(REG_SECD,&datu,1);
		
	if(datu&0x80)
	{// 发生调电事件,复位器件
		
		datu = 0;
		
		I2WR(REG_CONTRL1,&datu,0);
		
		return 1;
	}
	else
	{
		return 0;
	}


}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -