245 lines
7.3 KiB
C
245 lines
7.3 KiB
C
/********************************************************************************
|
||
Copyright (C), Sinowealth Electronic. Ltd.
|
||
Author: Sino
|
||
Version: V0.0
|
||
Date: 2020/04/26
|
||
History:
|
||
V2.0 2020/04/26 Preliminary
|
||
********************************************************************************/
|
||
#include "Main.h"
|
||
|
||
|
||
BOOL bRTCErr;
|
||
BOOL bRTCTwiRWErr;
|
||
U8 xdata ucRTCTwiRWErrDelayCnt;
|
||
RTC_VAR xdata RTC; //For External RTC
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCTwiCheck
|
||
* 参 数: 无
|
||
* 返回值: 无
|
||
* 描 述: 连续5S检测到RTC的I2C通讯错误,则置位bRTCErr=1
|
||
*************************************************************************************************/
|
||
void RTCTwiCheck(void)
|
||
{
|
||
if(bEnEEPRomBK)
|
||
{
|
||
if(bRTCTwiRWErr)
|
||
{
|
||
if(++ucRTCTwiRWErrDelayCnt >= TIME_1S_5S)
|
||
{
|
||
bRTCErr = 1;
|
||
ucRTCTwiRWErrDelayCnt = TIME_1S_5S;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
ucRTCTwiRWErrDelayCnt = 0;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCWrite
|
||
* 参 数: WrAddr: 寄存器地址;Length:数据长度;WrBuf:数据缓存Buf
|
||
* 返回值: 无
|
||
* 描 述: RTC写寄存器操作,如果出错连续写两次
|
||
*************************************************************************************************/
|
||
BOOL RTCWrite(U8 WrAddr, U8 Length, U8 xdata *WrBuf)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 i;
|
||
|
||
if(!bRTCErr)
|
||
{
|
||
for(i=0; i<5; i++)
|
||
{
|
||
#ifdef TWI_Hardware_Module
|
||
if(TwiWrite(RTC_ID, WrAddr, TWI_ADDR_1B, Length, TWI_CRC_NO, WrBuf))
|
||
{
|
||
Result = 1;
|
||
break;
|
||
}
|
||
#else
|
||
if(Result = TwiWrite(RTC_ID, WrAddr, Length, WrBuf))
|
||
{
|
||
Result = 1;
|
||
break;
|
||
}
|
||
#endif
|
||
Delay1ms(1);
|
||
}
|
||
}
|
||
bRTCTwiRWErr = !Result;
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCRead
|
||
* 参 数: RdAddr: 寄存器地址;Length:数据长度;WrBuf:数据缓存Buf
|
||
* 返回值: 无
|
||
* 描 述: RTC读寄存器操作,如果出错连续读两次
|
||
*************************************************************************************************/
|
||
BOOL RTCRead(U8 RdAddr, U8 Length, U8 xdata *RdBuf)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 i;
|
||
|
||
if(!bRTCErr)
|
||
{
|
||
for(i=0; i<5; i++)
|
||
{
|
||
#ifdef TWI_Hardware_Module
|
||
if(TwiRead(RTC_ID, RdAddr, TWI_ADDR_1B, Length, TWI_CRC_NO, RdBuf))
|
||
{
|
||
Result = 1;
|
||
break;
|
||
}
|
||
#else
|
||
if(TwiRead(RTC_ID, RdAddr, Length, RdBuf))
|
||
{
|
||
Result = 1;
|
||
break;
|
||
}
|
||
#endif
|
||
Delay1ms(1);
|
||
}
|
||
}
|
||
bRTCTwiRWErr = !Result;
|
||
|
||
return Result;
|
||
}
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCReadTime
|
||
* 参 数: RdAddr: 寄存器地址;Length:数据长度;WrBuf:数据缓存Buf
|
||
* 返回值: 无
|
||
* 描 述: RTC读寄存器操作,如果出错连续读两次
|
||
*************************************************************************************************/
|
||
BOOL RTCReadTime(RTC_VAR xdata *RtcRdVal)
|
||
{
|
||
U8 xdata rtcbuf[9];
|
||
BOOL Result = 0;
|
||
|
||
if(RTCRead(0x00, 9, &rtcbuf)) //从RTC读取时间
|
||
{
|
||
if((rtcbuf[7]&0x01) == 0x00) //judge RTCF bit,看是否曾经掉过电
|
||
{
|
||
if( ((rtcbuf[2]&0x80) == 0) //不是24小时制
|
||
|| ((rtcbuf[0]&0x70) > 0x50) || ((rtcbuf[0]&0x0F) > 0x09) || ((rtcbuf[0]&0x7F) > 0x59)
|
||
|| ((rtcbuf[1]&0x70) > 0x50) || ((rtcbuf[1]&0x0F) > 0x09) || ((rtcbuf[1]&0x7F) > 0x59)
|
||
|| ((rtcbuf[2]&0x30) > 0x20) || ((rtcbuf[2]&0x0F) > 0x09) || ((rtcbuf[2]&0x2F) > 0x24)
|
||
|| ((rtcbuf[3]&0x30) > 0x30) || ((rtcbuf[3]&0x0F) > 0x09) || ((rtcbuf[3]&0x3F) > 0x31) || (!(rtcbuf[3]&0x3F))
|
||
|| ((rtcbuf[4]&0x10) > 0x10) || ((rtcbuf[4]&0x0F) > 0x09) || ((rtcbuf[4]&0x1F) > 0x12) || (!(rtcbuf[4]&0x1F))
|
||
|| ((rtcbuf[5]&0xF0) > 0x90) || ((rtcbuf[5]&0x0F) > 0x09) || ((rtcbuf[5]&0xFF) > 0x99)
|
||
|| ((rtcbuf[6]&0x07) > 0x06) ) //对小时制及数据合法性进行检查
|
||
{
|
||
rtcbuf[0] = RtcRdVal->Second; //数据不合法,可能是因为RTC未初始化导致
|
||
rtcbuf[1] = RtcRdVal->Minute;
|
||
rtcbuf[2] = RtcRdVal->Hour;
|
||
rtcbuf[3] = RtcRdVal->Date;
|
||
rtcbuf[4] = RtcRdVal->Month;
|
||
rtcbuf[5] = RtcRdVal->Year;
|
||
rtcbuf[6] = RtcRdVal->Week;
|
||
|
||
Result = RTCModifyTime((RTC_VAR xdata *)(&rtcbuf));
|
||
}
|
||
else
|
||
{
|
||
RtcRdVal->Second = rtcbuf[0]; //数据合法,则保存从RTC读回的时间
|
||
RtcRdVal->Minute = rtcbuf[1];
|
||
RtcRdVal->Hour = rtcbuf[2]&0x1F;
|
||
RtcRdVal->Date = rtcbuf[3];
|
||
RtcRdVal->Month = rtcbuf[4];
|
||
RtcRdVal->Year = rtcbuf[5];
|
||
RtcRdVal->Week = rtcbuf[6];
|
||
|
||
Result = 1;
|
||
}
|
||
}
|
||
else //曾经掉电过,认为RTC不准。
|
||
{
|
||
Result = RTCModifyTime((RTC_VAR xdata *)RtcRdVal); //将当前的时间,或从E2中读取的时间,或固定时间重新写入RTC
|
||
}
|
||
}
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCModifyTime
|
||
* 参 数: RTC:将RTC参数传递进来,进行RTC更新
|
||
* 返回值: 无
|
||
* 描 述: RTC读寄存器操作,如果出错连续读两次
|
||
*************************************************************************************************/
|
||
BOOL RTCModifyTime(RTC_VAR xdata *RtcMdyVal)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 xdata rtcdata;
|
||
U8 xdata rtctemp[7];
|
||
|
||
rtcdata = 0x90;
|
||
Result = RTCWrite(RTC_REG_STATUS, 1, &rtcdata);
|
||
|
||
rtctemp[0] = RtcMdyVal->Second;
|
||
rtctemp[1] = RtcMdyVal->Minute;
|
||
rtctemp[2] = RtcMdyVal->Hour|0x80; //设置为24小时制
|
||
rtctemp[3] = RtcMdyVal->Date;
|
||
rtctemp[4] = RtcMdyVal->Month;
|
||
rtctemp[5] = RtcMdyVal->Year;
|
||
rtctemp[6] = RtcMdyVal->Week;
|
||
|
||
Result = RTCWrite(RTC_REG_SECOND, 7, (U8 xdata *)&rtctemp);
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
/*************************************************************************************************
|
||
* 函数名: RTCInitTime
|
||
* 参 数: RTC:将RTC参数传递进来,进行RTC初始化
|
||
* 返回值: 无
|
||
* 描 述: 初始化,从EEP读取保存的RTC时间参数进行第一次初始化,如果EEP没有保存,则默认初始化时间:20年5月1日12点
|
||
*************************************************************************************************/
|
||
BOOL RTCInitTime(RTC_VAR xdata *RtcInitVal)
|
||
{
|
||
BOOL Result = 0;
|
||
U8 xdata rtcbuf[9];
|
||
U8 xdata i;
|
||
U8 xdata checksum = 0;
|
||
|
||
MemorySet(rtcbuf, 0, sizeof(rtcbuf));
|
||
|
||
E2PRomRead(E2PROM_RTC_ADDR, 9, rtcbuf); //从E2备份区读出RTC数据
|
||
for(i=0; i<7; i++)
|
||
{
|
||
checksum += rtcbuf[i];
|
||
}
|
||
|
||
if((rtcbuf[7]!=checksum) || (rtcbuf[8]!=0x5a)) //若校验失败,说明E2读出的时间不可靠,直接把出厂时间拿来用
|
||
{
|
||
rtcbuf[0] = 0x00; //second
|
||
rtcbuf[1] = 0x00; //minute
|
||
rtcbuf[2] = 0x12; //hour
|
||
rtcbuf[3] = 0x01; //date
|
||
rtcbuf[4] = 0x05; //month
|
||
rtcbuf[5] = 0x20; //year
|
||
rtcbuf[6] = 0x05; //week
|
||
}
|
||
|
||
MemoryCopy(rtcbuf, (U8 xdata *)RtcInitVal, 7); //从E2读出的时间或出厂时间先放到RTC时间寄存器中存起来
|
||
Result = RTCReadTime((RTC_VAR xdata *)RtcInitVal);
|
||
|
||
return Result;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|