📄 rtc_dsp.c
字号:
//**********************************************************
//读取温度值
//**********************************************************
uchar Temp_Read(void)
{
uchar Temp[2],Addr[2],Len[2];
uchar i=0;
Temp[0] = 0x00;
//工作方式配置
Addr[0] = LM75;
Addr[1] = 0x01; //配置地址
Len[0] = 0x02;
Len[1] = 0x01;
while(ISendStr(Addr,Temp,Len)==0)
{
i++;
if(i>=0x20) break; //最多写32次
}
i = 0xFF;
while(i--); //i=0;
//读取温度值
Addr[1] = 0x00;//温度值地址
Len[1] = 0x02;
i = 0;
while(IRcvStr(Addr,Temp,Len)==0) //读取当前温度
{
i++;
if(i>=0x20) return 20; //最多读32次,否则返回年平均温度20
}
return Temp[0];
}
//**********************************************************
//温度补偿算法
//**********************************************************
void Temp_Equalize(void)
{
uchar Temp;
Temp = Temp_Read();
if(Temp&0x80) //温度零下
{
Temp = ~Temp+1+70;
if(Temp>90) Temp = 90; //低于负20度
}
else
{
if(Temp>70) Temp = 70; //高于70度
if(Temp>=50)
{
MSSum += Temp; //高温>=50度偏置补偿
if(Temp>=60) MSSum += 100;
}
}
MSSum += Equalize_Table[Temp]; //误差累加
if(MSSum>=1000) //时间补偿1秒
{
SECINC();
RTC_Set(0x00,RTC,0x07);
MSSum -= 1000;
}
}
//**********************************************************
//刷新显示数据
//**********************************************************
void Display(uchar idata *ptr)
{
uchar Temp[2],Addr[3],Len[2];
//HL6024初始化
Addr[0] = HL6024; //HL6024器件地址
Len[0] = 0x01; //无子地址
Len[1] = 0x02;
Temp[0] = PWR_MODE|0x80; //模式选择指令
Temp[1] = OFF_GLITTER; //闪烁选择指令
if(CommLCDSec>0) Temp[1] = ON_GLITTER;
ISendStr(Addr,Temp,Len);
//HL6024显示数据写入
Addr[1] = 0xE0; //HL6024器件子地址
Addr[2] = 0x00; //HL6024待写数据的RAM区首地址
Len[0] = 0x03;
Len[1] = 0x08;
ISendStr(Addr,ptr,Len);
if(CommFlag==0) COMMSEL = 0;
}
//**********************************************************
//历史月份计算
//说明:查找以当前月份为基准的上12个月以内的月份。举例:假设
//当前月份为1月,上2(sn=1)月为11月(1+10-1=10).
//入口参数:sn=0代表要查找的为上(sn+1)1月,依此类推.
//**********************************************************
uchar LastMonthSN(uchar sn)
{
uchar Temp1;
uchar Temp2;
Temp1 = 0x00;
Temp2 = sn;
Temp1 = BCD2HEX(Month)+10-Temp2;
if(Temp1>=12) Temp1 -= 12;
return Temp1;
}
//**********************************************************
//时间检查
//**********************************************************
bit TimeCHK(uchar idata *ptr)
{
uchar Temp[3];
Temp[0] = *ptr;//秒
ptr++;
Temp[1] = *ptr;//分
ptr++;
Temp[2] = *ptr;//时
if((BCDCHK(Temp,0x03)==0)||(Temp[0]>0x59)||(Temp[1]>0x59)||(Temp[2]>0x23)) return(0);
return(1);
}
//**********************************************************
//日期检查
//**********************************************************
bit DateCHK(uchar idata *ptr)
{
uchar Temp[3];
Temp[0] = *ptr;//日
ptr++;
Temp[1] = *ptr;//月
ptr++;
Temp[2] = *ptr;//年
if((BCDCHK(Temp,0x03)==0)||(Temp[0]==0x00)||(Temp[1]==0x00)||(Temp[1]>0x12)) return(0);
if(Temp[1]==0x02)
{
if(Temp[0]>0x28)
{
if((BCD2HEX(Temp[2])&0x03)==0x00)//闰年
{
if(Temp[0]>0x29) return(0);
}
else return(0);
}
}
else if((Temp[1]==0x04)||(Temp[1]==0x06)||(Temp[1]==0x09)||(Temp[1]==0x11))
{
if(Temp[0]>0x30) return(0);
}
else
{
if(Temp[0]>0x31) return(0);
}
return(1);
}
//**********************************************************
//名称: uchar pt(uchar year,uchar month)
//功能:
//说明:
//**********************************************************
uchar pt(uchar year,uchar month)
{
//unsigned int idata tYear;
//tYear = year+2000;
uchar tYear;
tYear = year;
switch(month)
{
case 1: return 31; break;
//case 2: return 28+(tYear%4==0&&(tYear%400==0||tYear%100!=0));break;
case 2: return 28+(tYear%4==0);break;
case 3: return 31; break;
case 4: return 30; break;
case 5: return 31; break;
case 6: return 30; break;
case 7: return 31; break;
case 8: return 31; break;
case 9: return 30; break;
case 10: return 31; break;
case 11: return 30; break;
case 12: return 31; break;
default: return 0; break;
}
}
//*****************************************************************************
//名称: long int DateDifferenceCal(uchar idata *pDate1,uchar idata *pDate2)
//功能: 日期时间差计算,返回两日期相差的天数;
//说明: *pDate1--->指向指定日期(smaller)的日所在地址;
// *pDate2--->指向指定日期(bigger)的日所在地址;
//*****************************************************************************
long int DateDifferenceCal(uchar idata *pDate1,uchar idata *pDate2)
{
uchar idata *p1,*p2,Date1[3],Date2[3]; //int year1,month1,day1,year2,month2,day2;
long int sum;
Watchdog_feed();
p1 = pDate1;
p2 = pDate2;
//读取日期1(smaller)
for(sum=0;sum<3;sum++)
{
Date1[sum] = BCD2HEX(*p1);
p1++;
}
//读取日期2(bigger)
for(sum=0;sum<3;sum++)
{
Date2[sum] = BCD2HEX(*p2);
p2++;
}
//日期比较
if( (Date1[2]>Date2[2]) || ((Date1[2]==Date2[2])&&(Date1[1]>Date2[1]))
|| ((Date1[2]==Date2[2])&&(Date1[1]==Date2[1])&&(Date1[0]>=Date2[0])) ) return(0);
//////////////////////////////////////////////////////////////////////////////////////
sum = Date2[0]; //日
for(;!((Date1[2]==Date2[2])&&(Date1[1]==Date2[1]));Date1[1]++)
{
sum += pt(Date1[2],Date1[1]);
if(Date1[1]>=12)
{
Date1[2]++;
Date1[1] = 0;
}
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
sum = sum-Date1[0];
///////////////////////////////////////////////////////////////////////////////////////
return sum;
}
//**********************************************************
//电能结算日期/反向数据清零时间判断
//参数:addr2--->CSI24C64片内地址2
//返回:当前时间与上次完成时间之间的月差
//**********************************************************
uchar BlnDateCheck(uchar addr2)
{
uchar Temp;
uchar TMonth[2];
uchar TBalance[3];
//上次电能结算日期(addr2=0x8B)/上次反向数据清零时间(addr2=0x4E)
Read24C64(TMonth,0x08,addr2,2);
if(TMonth[0]!=~TMonth[1])
{
if(Month==0x01) TMonth[0]=12; //默认上次结算为当前月-1
else TMonth[0]=BCD2HEX(Month)-1;
}
//读取自动抄表日期
Read24C64(TBalance,0x08,0x88,3);
Temp = TBalance[0]+TBalance[1];
//写入默认月末24时冻结时间(00:00)
if(TBalance[2]!=~Temp)
{
TBalance[0] = 0x00;//时
TBalance[1] = 0x01;//日
TBalance[2] = 0xFE;//校验
Write24C64(TBalance,0x08,0x88,3);
}
//月判断
TMonth[1] = BCD2HEX(Month); //当前月份
//Temp = TMonth[1]; //当前月份HEX数据
if(TMonth[1]<TMonth[0]) TMonth[1] += 12; //跨年
TMonth[1] -= TMonth[0];
if(TMonth[1]>0x01) //大于1个月
{
TBalance[2] = TMonth[1]; //结算标志
if( (Day<TBalance[1]) || ((Day==TBalance[1])&&(Hour<TBalance[0])) )
{//防止停电时错误结算事件发生:比如结算日为18号,3月19号停电,5月12号来电
CurrentMonthNoBlnFlag = 0x01; //本月电量不结算标志
isLastMonthEry = 0x01; //抄收上月电量标志(用于非1日0时结算的抄表日)
}
}
else if(TMonth[1]==0x01) //等于一个月
{
if(Day>TBalance[1]) TBalance[2]=0x01; //超过结算日
else if((Day==TBalance[1])&&(Hour>=TBalance[0])) TBalance[2] = 0x01; //超过结算日时
else
{
TBalance[2] = 0x00;
isLastMonthEry = 0x01; //抄收上月电量标志(用于非1日0时结算的抄表日)
}
}
else TBalance[2] = 0x00;
return(TBalance[2]);
}
//**********************************************************
//开表盖事件处理
//**********************************************************
void KBG_Even_Proc(void)
{
uchar Temp;
//开表盖事件监测
if(KBG==0)
{
KBGDeLayTimer++;
}
else
{
KBGSec = 0x00;
KBGDeLayTimer = 0x00;
KBG_Last_State = 1; //刷新为高电平,为下次判断做准备
}
//开表盖事件判断
if(KBGDeLayTimer>5)
{
if(KBG_Last_State==1) //上次为高电平,即发生开表盖事件
{
KBG_Last_State = 0; //刷新为低电平,为下次判断作参考
Read24C64(CommVariant,0x09,0x00,5); //读取最近一次开表盖时间
Temp = ~SumCHK(CommVariant,4);
if(CommVariant[4]!=Temp)
{
ArrayInit(CommVariant,4);
CommVariant[4] = 0xFF;
}
//转写为上一次开表盖时间
Write24C64(CommVariant,0x09,0x0A,5);
//RTC_Read();
CommVariant[0] = Min;
CommVariant[1] = Hour;
CommVariant[2] = Day;
CommVariant[3] = Month;
CommVariant[4] = ~SumCHK(CommVariant,4);
//写为最近一次开表盖时间
Write24C64(CommVariant,0x09,0x00,5);
//读取开表盖累计次数
Read24C64(CommVariant,0x09,0x1C,3);
Temp = CommVariant[0]+CommVariant[1];
if(CommVariant[2]!=~Temp)
{
CommVariant[0] = 0x00;
CommVariant[1] = 0x00;
}
BCDINC(CommVariant,2); //+1
CommVariant[2] = ~(CommVariant[0]+CommVariant[1]);
//重新写入开表盖累计次数
Write24C64(CommVariant,0x09,0x1C,3);
}
}
//开表盖时间累计
if(KBG_Last_State==0) KBGSec++;
if(KBGSec>59) //开表盖时间累计满1分钟处理
{
KBGSec = 0x00;
Read24C64(CommVariant,0x09,0x14,4); //读取开表盖时间
Temp = CommVariant[0]+CommVariant[1]+CommVariant[2];
if(Temp!=~CommVariant[3]) ArrayInit(CommVariant,3); //数据错误,清零
BCDINC(CommVariant,3); //+1
CommVariant[3] = ~(CommVariant[0]+CommVariant[1]+CommVariant[2]);
Write24C64(CommVariant,0x09,0x14,4); //回写开表盖时间
}
}
//**********************************************************
//开端钮盒事件处理
//**********************************************************
void KDNH_Even_Proc(void)
{
uchar Temp;
//开端钮盒事件监测
if(KDNH==1)
{
KDNHDeLayTimer++;
}
else
{
KDNHSec = 0x00;
KDNHDeLayTimer = 0x00;
KDNH_Last_State = 0; //刷新为低电平,为下次判断做准备
}
//开端钮盒事件判断
if(KDNHDeLayTimer>5)
{
if(KDNH_Last_State==0) //上次为低电平,即发生开端钮盒事件
{
KDNH_Last_State = 1; //刷新为高电平,为下次判断作参考
Read24C64(CommVariant,0x09,0x05,5); //读取最近一次开端钮盒时间
Temp = ~SumCHK(CommVariant,4);
if(CommVariant[4]!=Temp)
{
ArrayInit(CommVariant,4);
CommVariant[4] = 0xFF;
}
//转写为上一次开端钮盒时间
Write24C64(CommVariant,0x09,0x0F,5);
//RTC_Read();
CommVariant[0] = Min;
CommVariant[1] = Hour;
CommVariant[2] = Day;
CommVariant[3] = Month;
CommVariant[4] = ~SumCHK(CommVariant,4);
//写为最近一次开端钮盒时间
Write24C64(CommVariant,0x09,0x05,5);
//读取开端钮盒累计次数
Read24C64(CommVariant,0x09,0x1F,3);
Temp = CommVariant[0]+CommVariant[1];
if(CommVariant[2]!=~Temp)
{
CommVariant[0] = 0x00;
CommVariant[1] = 0x00;
}
BCDINC(CommVariant,2); //+1
CommVariant[2] = ~(CommVariant[0]+CommVariant[1]);
//重新写入开端钮盒累计次数
Write24C64(CommVariant,0x09,0x1F,3);
}
}
//开端钮盒时间累计
if(KDNH_Last_State==1) KDNHSec++;
if(KDNHSec>59) //开端钮盒时间累计满1分钟处理
{
KDNHSec = 0x00;
Read24C64(CommVariant,0x09,0x18,4); //读取开端钮盒时间
Temp = CommVariant[0]+CommVariant[1]+CommVariant[2];
if(Temp!=~CommVariant[3]) ArrayInit(CommVariant,3); //数据错误,清零
BCDINC(CommVariant,3); //+1
CommVariant[3] = ~(CommVariant[0]+CommVariant[1]+CommVariant[2]);
Write24C64(CommVariant,0x09,0x18,4); //回写开端钮盒时间
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -