ZDBMS/code_drv/RTC.c

245 lines
7.3 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/********************************************************************************
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;
}