📄 rtc.c
字号:
/****************************************************************************
* 名 称: I2CWrByte()
* 功 能: I2C写字节
* 入口参数:
* 出口参数:
****************************************************************************/
uint8 RTCI2CWrByte(uint8 type,uint8 Addr,uint8 data)
{
uint8 temp=0;
I2CONCLR=0x2c; // 清除AA,SI,STA
I2CONSET=0x60; // 使能IIC,发送起始位
I2CDelayWait();
temp=I2CWrCommand(type); // 写操作 I2C器件本身地址
if (temp==FALSE)
return FALSE;
temp=I2CWrCommand(Addr & 0xff);
if (temp==FALSE)
return FALSE;
temp=I2CWrCommand(data); // 写入数据
if (temp==FALSE)
return FALSE;
I2CONSET=0x10; // 发送停止位
I2CONCLR = 0x08;
return TRUE;
}
/****************************************************************************
* 名 称: I2CRdByte()
* 功 能: I2C读字节
* 入口参数:
* 出口参数:
****************************************************************************/
uint8 RTCI2CRdByte(uint8 type,uint8 Addr)
{
uint8 temp=0;
//首先进行写地址操作
I2CONCLR=0x2c; // 清除AA,SI,STA
I2CONSET=0x60; // 使能IIC,发送起始位
I2CDelayWait();
temp=I2CWrCommand(type); // 写操作
if (temp==FALSE)
return FALSE;
temp=I2CWrCommand(Addr & 0xff);
if (temp==FALSE)
return FALSE;
//开始读时序
I2CONSET=0x20; // 发送起始位
I2CONCLR=0x08; // 清除SI
I2CDelayWait();
temp=I2CWrCommand(type + 1); // 声明读操作
if (temp==FALSE)
return FALSE;
I2CONCLR = 0x2c;
I2CDelayWait();
temp=I2STAT;
temp=I2DAT;
I2CONSET=0x50; //发送停止位
I2CONCLR = 0x08;
return temp;
}
/****************************************************************************
* 名 称: RTC_SetClockData()
* 功 能: 设置RTC初始时钟
* 入口参数: *pClock:初始时钟数据地址 S M H D M W Y C(7Byte BCD码 + 1控制字)
* 出口参数:
****************************************************************************/
void RTC_SetClockData(DateTimeType *pClock)
{
unsigned char ab;
RTCI2CWrByte(ISL12022,ISL_INT,0X4A); //1S脉冲
ab = RTCI2CRdByte(ISL12022,ISL_BETA);
ab |= 0xe0;
RTCI2CWrByte(ISL12022,ISL_BETA,ab); //使能温补
RTCI2CWrByte(ISL12022,ISL_SECOND,pClock->second);
RTCI2CWrByte(ISL12022,ISL_MINUTE,pClock->minute);
ab = pClock->hour;
ab |= 0x80;
RTCI2CWrByte(ISL12022,ISL_HOUR,ab);
RTCI2CWrByte(ISL12022,ISL_DAY,pClock->day);
RTCI2CWrByte(ISL12022,ISL_MONTH,pClock->month);
RTCI2CWrByte(ISL12022,ISL_YEAR,pClock->year);
RTCI2CWrByte(ISL12022,ISL_WEEK,pClock->week);
return;
}
/****************************************************************************
* 名 称: RTC_GetClockData()
* 功 能: 获取RTC的当前时间 S M H D M W Y (7Byte BCD码)
* 入口参数: *pClock:读取当前时间存储区
* 出口参数:
****************************************************************************/
void RTC_GetClockData(DateTimeType *pClock)
{
unsigned char ab;
pClock->second = RTCI2CRdByte(ISL12022,ISL_SECOND);
pClock->minute = RTCI2CRdByte(ISL12022,ISL_MINUTE);
ab = RTCI2CRdByte(ISL12022,ISL_HOUR);
pClock->hour = ab&0x7f;
pClock->day = RTCI2CRdByte(ISL12022,ISL_DAY);
pClock->month = RTCI2CRdByte(ISL12022,ISL_MONTH);
pClock->year = RTCI2CRdByte(ISL12022,ISL_YEAR);
pClock->week = RTCI2CRdByte(ISL12022,ISL_WEEK);
}
/****************************************************************************
* 名 称: InitRTC()
* 功 能: 初始化
* 入口参数:
* 出口参数:
****************************************************************************/
void InitRTC(void)
{
unsigned char ab;
RTCI2CWrByte(ISL12022,ISL_INT,0X4A); //1S脉冲
ab = RTCI2CRdByte(ISL12022,ISL_BETA);
ab |= 0xe0;
RTCI2CWrByte(ISL12022,ISL_BETA,ab); //使能温补
}
/****************************************************************************
* 名 称: Init_RTC()
* 功 能: 初始化RTC
* 入口参数:
* 出口参数:
****************************************************************************/
void RTC_Init(void)
{
uint8 week1=0;
uint8 flag = 0;
uint8 i;
for(i=0;i<3;i++)
{
InitRTC();
RTC_GetClockData(&SysDateTime);
if(Bcd2Byte(SysDateTime.year) < 0x05)
flag = 1;
if((Bcd2Byte(SysDateTime.month) < 1)||(Bcd2Byte(SysDateTime.month) > 12))
flag = 1;
if((Bcd2Byte(SysDateTime.day) < 1)||(Bcd2Byte(SysDateTime.day) > 31))
flag = 1;
if(Bcd2Byte(SysDateTime.hour) > 23)
flag = 1;
if(Bcd2Byte(SysDateTime.minute) > 59)
flag = 1;
if(Bcd2Byte(SysDateTime.second) > 59)
flag = 1;
if(flag == 0)
break;
}
if(flag == 1)
{
SysDateTime.year = 0x08;
SysDateTime.month = 0x05;
SysDateTime.day = 0x01;
SysDateTime.hour = 0x00;
SysDateTime.minute = 0x00;
SysDateTime.second = 0x00;
RtcSetClockFlag = VALID_FLAG;
}
week1 = GetWeek(SysDateTime.year,SysDateTime.month,SysDateTime.day);
if((SysDateTime.week != week1)||(SysDateTime.second & 0x80)||(flag == 1))
{
SysDateTime.week = week1;
SysDateTime.second &= 0x7f;
RTC_SetClockData(&SysDateTime);
InitRTC();
}
DisplayTime(0,11,(DateTimeType *)&SysDateTime);
}
/****************************************************************************
* 名 称: Init_Clock()
* 功 能: 初始化时钟
* 入口参数:
* 出口参数:
****************************************************************************/
void Init_Clock(DateTimeType *pDateTime)
{
DateTimeType gDateTime;
gDateTime.year = pDateTime->year;
gDateTime.month = pDateTime->month;
gDateTime.day = pDateTime->day;
gDateTime.hour = pDateTime->hour;
gDateTime.minute = pDateTime->minute;
gDateTime.second = pDateTime->second;
gDateTime.week = SysDateTime.week;
gDateTime.week = GetWeek(gDateTime.year,gDateTime.month,gDateTime.day);
RTC_SetClockData(&gDateTime);
InitRTC();
}
///////////////////////////////////////////////////////////////////
#endif
/****************************************************************************
* 名 称: HandleDateTimeMessage()
* 功 能: 处理时钟消息
* 入口参数:
* 出口参数:
****************************************************************************/
void HandleDateTimeMessage(void)
{
uint8 flag = 0;
DateTimeType gDateTime;
memset((uint8 *)&gDateTime,0,sizeof(DateTimeType));
if(RtcSetClockFlag == VALID_FLAG)
{
if(++RtcSetClockTime > 30)
{
if((MeasurePara[1].DI8900 == MEASURE_VALID)&&(MeasurePara[1].DI8901 == MEASURE_TYPE_RS485)
&&(MeasurePara[1].DI8903 == MEASURE_RULE_GB)&&(gMeterComm[1].status == METER_COMM_SUCC))
{
if((Bcd2Byte(DIC010Addr[1].DIC010.year) < 0x05)||((Bcd2Byte(DIC010Addr[1].DIC010.year) > 20)))
flag = 1;
if((Bcd2Byte(DIC010Addr[1].DIC010.month) < 1)||(Bcd2Byte(DIC010Addr[1].DIC010.month) > 12))
flag = 1;
if((Bcd2Byte(DIC010Addr[1].DIC010.day) < 1)||(Bcd2Byte(DIC010Addr[1].DIC010.day) > 31))
flag = 1;
if(Bcd2Byte(DIC010Addr[1].DIC011.hour) > 23)
flag = 1;
if(Bcd2Byte(DIC010Addr[1].DIC011.minute) > 59)
flag = 1;
if(Bcd2Byte(DIC010Addr[1].DIC011.second) > 59)
flag = 1;
if(flag != 1)
{
SysDateTime.year = DIC010Addr[1].DIC010.year;
SysDateTime.month = DIC010Addr[1].DIC010.month;
SysDateTime.day = DIC010Addr[1].DIC010.day;
SysDateTime.hour = DIC010Addr[1].DIC011.hour;
SysDateTime.minute = DIC010Addr[1].DIC011.minute;
SysDateTime.second = DIC010Addr[1].DIC011.second;
}
InitRTC();
RTC_SetClockData(&SysDateTime);
RtcCmpTime = 0;
}
RtcSetClockTime = 0;
RtcSetClockFlag = 0;
}
}
if(++RtcCmpTime >= 10)
{
RtcCmpTime = 0;
InitRTC();
RTC_GetClockData(&gDateTime);
InitRTC();
if((gDateTime.second & 0x80)||(Bcd2Byte(gDateTime.year) > 20)||(Bcd2Byte(gDateTime.month) > 12)||(Bcd2Byte(gDateTime.day) > 31))
{
SysDateTime.second &= 0x7f;
InitRTC();
RTC_SetClockData(&SysDateTime);
InitRTC();
RTC_GetClockData(&gDateTime);
InitRTC();
if(gDateTime.second & 0x80)
{
SysDateTime.second &= 0x7f;
RTC_SetClockData(&SysDateTime);
InitRTC();
}
RtcSetClockFlag = VALID_FLAG;
}
else
memcpy((uint8 *)&SysDateTime,(uint8 *)&gDateTime,sizeof(DateTimeType));
}
TerminalPara.DI8030.year = SysDateTime.year;
TerminalPara.DI8030.month = SysDateTime.month;
TerminalPara.DI8030.day = SysDateTime.day;
TerminalPara.DI8030.hour = SysDateTime.hour;
TerminalPara.DI8030.minute = SysDateTime.minute;
TerminalPara.DI8030.second = SysDateTime.second;
}
/****************************************************************************
* 名 称: HandleRTCTimer()
* 功 能: 处理时钟时间
* 入口参数:100ms
* 出口参数:
****************************************************************************/
void HandleRTCTimer(void)
{
uint16 i;
if(RtcInitFlag == INVALID_FLAG)
{
if(++RtcInitTime >= RTC_INIT_TIME)
{
RtcInitTime = 0;
RtcInitFlag = VALID_FLAG;
for(i=0;i<500;i++);
RTC_Init();
for(i=0;i<500;i++);
SystemClockOKFlag = VALID_FLAG;
OldSystemTimeMin = SysDateTime.minute; //产生1MIN变量实始化
InitNoPowerTime(); //初始化终端停电时间
}
}
}
/****************************************************************************
* 名 称: Cal_MonthDayNum()
* 功 能: 算出某年某月有多少天
* 说 明: 如果能被4整除而不能被100整除/能被400整除的年份为润年,
当年2月为29天
* 方 法: 先计算月份的天数,再计算从1900开始到待求日期的天数,
最后求出星期(1900.1.1是星期一)
****************************************************************************/
uint8 Cal_MonthDayNum(uint16 year,uint8 month)
{
if(month==2)
{
return(((year%4==0)&&(year%100!=0)||(year%400==0))?29:28);
}
else
return(monthday[month-1]);
}
/****************************************************************************
* 名 称: Cal_Week()
* 功 能: 计算某年某月某日是星期几(1900年开始)
* 说 明: 计算从1900到当天的天数除7所得余数就是星期几
****************************************************************************/
uint8 Cal_Week(uint16 year,uint8 month,uint8 day)
{
uint32 daynum=0;
uint16 i;
if ((year > 1900)&&( month >= 1)&&(month <= 12)&&(day >0)&&(day <= 31))
{
for(i=1900;i<year;i++)
{
daynum = daynum + (((i%4==0)&&(i%100!=0)||(i%400==0))?366:365);
}
for(i=1;i<month;i++)
{
daynum = daynum + Cal_MonthDayNum(year,i);
}
daynum = daynum + day;
return(daynum%7);
}
else
{
return 8; //"8"表示输入的年月日出错
}
}
/****************************************************************************
* 名 称: GetWeek()
* 功 能: 获取星期
* 说 明: year,month,day:都为BCD码,返回week也为BCD码(或HEX)
****************************************************************************/
uint8 GetWeek(uint8 year,uint8 month,uint8 day)
{
uint16 year1=0;
uint8 month1=0;
uint8 day1=0;
uint8 week = 0;
year1 = Bcd2Byte(year) + 2000;
month1 = Bcd2Byte(month);
day1 = Bcd2Byte(day);
week = Cal_Week(year1,month1,day1);
return week;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -