📄 pcf8563.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 + -