📄 rtc_dsp.c
字号:
EryBln_Flag = 0; //清电量结算标志
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
//**********************************************************
// 名称: MeterStateChange()
// 功能: 电表在新进状态时,连续运行36小时后自动切换至运行状态
// 说明:
//**********************************************************
void MeterStateChange(void)
{
uchar Temp,TMonth[2];
Temp = isNewState & 0x80;
if(Temp==0x80)
{
isNewState++; //小时加1
Temp = isNewState & 0x7F;
if(Temp>=36)
{
isNewState = 0x00;
//读取电表管理状态
Read24C64(TMonth,0x00,0xEE,2);
//电表切换至运行状态
TMonth[0] |= 0x02;
TMonth[1] = ~TMonth[0];
Write24C64(TMonth,0x00,0xEE,2);
}
}
else isNewState = 0x00;
}
//**********************************************************
// 名称: Fee_CHK()
// 功能: 时段费率检查
// 说明:
//**********************************************************
void Fee_CHK(void)
{
uchar i,TFee;
uchar TFlag1,TFlag2;
uchar yCodeTime,nCodeTime;
uchar ySeasonTime;
uchar TChangeMode;
uchar Temp[2],Num[6];
//读(时段表切换及标志+校验和)
Read24C64(CommVariant,0x09,0x40,7);
CommVariant[7] = ~SumCHK(CommVariant,6); //校验和
if(CommVariant[7]!=CommVariant[6])
{
CommVariant[0] = 0x20; //默认为时段表1,按编号切换
CommVariant[1] = 0x00; //分
CommVariant[2] = 0x00; //时
CommVariant[3] = 0x00; //日
CommVariant[4] = 0x00; //月
CommVariant[5] = 0x00; //年
CommVariant[6] = 0xDF; //校验和
Write24C64(CommVariant,0x09,0x40,7); //写入EE
}
TChangeMode = CommVariant[0]&0x20; //获取时段表切换方式
//获取当前所要参考的日时段表
if(TChangeMode==0x20)//按编号切换
{
yCodeTime = 0xA5; //按编号切换时间到
if( (Year>CommVariant[5]) || ((Year==CommVariant[5])&&(Month>CommVariant[4]))
|| ((Year==CommVariant[5])&&(Month==CommVariant[4])&&(Day>CommVariant[3]))
|| ((Year==CommVariant[5])&&(Month==CommVariant[4])&&(Day==CommVariant[3])&&(Hour>CommVariant[2]))
|| ((Year==CommVariant[5])&&(Month==CommVariant[4])&&(Day==CommVariant[3])&&(Hour==CommVariant[2])&&(Min>=CommVariant[1]))
) i = CommVariant[0]&0x01;
else //按编号切换时间未到
{
yCodeTime = 0x00;
nCodeTime = 0x00;
//读取上次切换方式,如果上次也是按编号方式切换,则读取上次按编号切换所选择的时段表号,
//并按此时段表号执行;如果上次是按季节方式切换,则转向按季节方式切换。
Read24C64(Temp,0x09,0x55,2); //读取上次切换方式标志字节
if(Temp[0]!=~Temp[1])
{
Temp[0] = 0x20; //默认上次为按编号切换
Temp[1] = 0xDF;
Write24C64(Temp,0x09,0x55,2); //写入EE
}
Temp[1] = Temp[0]&0x20;
if(Temp[1]==0x20) //上次为按编号切换
{
nCodeTime = 0xA5;
i = Temp[0]&0x01; //获取上次按编号切换所选择的时段表号
}
else TChangeMode = 0x00; //上次为按季节切换
}
}
if(TChangeMode==0x00) //按季节切换
{
yCodeTime = 0x00; //按编号切换时间未到
nCodeTime = 0x00;
//读取时区1、2起始日期与时段表号
Read24C64(CommVariant,0x09,0x47,8);
CommVariant[8] = ~SumCHK(CommVariant,3); //校验和
CommVariant[9] = ~SumCHK(&CommVariant[3],3); //校验和
//可在此添加判断时区1、2起始日期大小的程序
if((CommVariant[8]!=CommVariant[6])||(CommVariant[9]!=CommVariant[7])) //读取时区1或2的起始日期与时段表号发生错误
{
CommVariant[0] = 0x00; //默认取时段表1
CommVariant[1] = 0x01; //日
CommVariant[2] = 0x05; //月
CommVariant[6] = 0xF9; //校验和
CommVariant[3] = 0x01; //默认取时段表2
CommVariant[4] = 0x01; //日
CommVariant[5] = 0x10; //月
CommVariant[7] = 0xED; //校验和
Write24C64(CommVariant,0x09,0x47,8); //若读数据发生错误,则修改相应eeprom数据
}
TFee = 1;
//判断当前所在时区,获取当前正在执行的时段表编号
Num[0] = Month; //当前月份
Num[1] = Day; //当前日期
if(Num[0]<CommVariant[2]) TFee = 2; //当前为时区2
else
{
if(Num[0]==CommVariant[2])
{
if(Num[1]<CommVariant[1]) TFee = 2; //当前为时区2
else TFee = 1; //当前为时区1
}
else //Num[0]>CommVariant[2]
{
if(Num[0]<CommVariant[5]) TFee = 1; //当前为时区1
else
{
if(Num[0]==CommVariant[5])
{
if(Num[1]<CommVariant[4]) TFee = 1; //当前为时区1
else TFee = 2; //当前为时区2
}
else TFee = 2; //当前为时区2
}
}
}
}
/////////////////////////////////////////////////////////////////////
Temp[0] = CommVariant[0] & 0x01; //时区1时段表编号
Temp[1] = CommVariant[3] & 0x01; //时区2时段表编号
if(TFee==2) Temp[0] = Temp[1];
if((yCodeTime!=0x00)||(nCodeTime!=0x00)) Temp[0] = i; //优先级高
//Temp[1] = ~Temp[0];
//写当前正在执行的时段表编号,日时段表切换时间、电量记录
//此段代码有待修改......
//********************************************************
Read24C64(Num,0x09,0x4F,6);
if(Num[0]!=~Num[1])
{
Num[0] = 0x00; //默认执行时段表1
Num[1] = 0xFF;
}
if(Num[2]!=~Num[3])
{
Num[2] = 0x01; //默认为时区1
Num[3] = 0xFE;
}
if(Num[4]!=~Num[5])
{
Num[4] = 0x00; //默认为未完成按编号切换
Num[5] = 0xFF;
}
//时段表号发生改变或时区号发生改变,且是按季节切换,则需冻结电量
ySeasonTime = 0x00;
if( ( (Num[0]!=Temp[0]) || (Num[2]!=TFee) ) && (TChangeMode==0x00) ) ySeasonTime = 0xA5;
if(Num[4]==0xA5) yCodeTime = 0x00; //已完成按编号切换
//if( (Num[0]!=Temp[0])||(ySeasonTime!=0x00)||(yCodeTime!=0x00) )
//{
if(Num[0]!=Temp[0])
{
Num[0] = Temp[0];
Num[1] = ~Temp[0];
}
if(ySeasonTime!=0x00)
{
Num[2] = TFee;
Num[3] = ~TFee;
}
if(yCodeTime!=0x00) //本次完成按编号切换
{
Num[4] = 0xA5;
Num[5] = 0x5A;
}
Write24C64(Num,0x09,0x4F,6);
//}
//**********************************************************************************
//发生按编号切换、时区发生变化或时段表发生变化,写日时段表切换时间、电量记录
if( (ySeasonTime!=0x00)||(yCodeTime!=0x00) )
{
///////////////////////////////////////////////
ePowerDownCheckFlag = DISABLE; //关闭掉电检测
///////////////////////////////////////////////
//形成(总/正)向有功指数数据块
CreateRealTimeEry();
for(i=47;i>15;i--) CommVariant[i] = CommVariant[i-16];
//读取当前时间
//RTC_Read();
CommVariant[10] = RTC[0]; //Sec
CommVariant[11] = RTC[1]; //Min
CommVariant[12] = RTC[2]; //Hour
CommVariant[13] = RTC[4]; //Day
CommVariant[14] = RTC[5]; //Month
CommVariant[15] = RTC[6]; //Year
//写入EE
Write24C64(&CommVariant[10],0x09,0x6A,22);
Write24C64(&CommVariant[32],0x09,0x80,16);
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
}
//**********************************************************************************
TFlag1 = 0x00;
//读取当前所在时段表数据
Read24C64(CommVariant,0x00,0x60+(Temp[0]&0x01)*0x20,25);
Temp[1] = ~SumCHK(CommVariant,24); //校验和
if(CommVariant[24]!=Temp[1]) //读当前时段表数据发生错误
{
TFlag1 = 0xA5;
}
//确定有效时段数
for(Temp[1]=0;Temp[1]<27;Temp[1]+=3)
{
//有效费率号: 01--尖,02--峰,03--平,04--谷
if((Temp[1]==24)||(CommVariant[Temp[1]]==0x00))
{
Num[0] = Temp[1]-1;//最大为8个时段,或者费率号出错
break;
}
}
//当前时段判断
TFlag2 = 0x00;
TFee = 0x00;
Num[1] = 0x00;
do
{
if(Num[1]==(Num[0]-2)) //时段表末尾
{
if(Hour<CommVariant[Num[0]]) { TFee=CommVariant[Num[1]-3]; }
else if(Hour==CommVariant[Num[0]])
{
if(Min<CommVariant[Num[0]-1])
{
TFee=CommVariant[Num[1]-3];
}
else TFee=CommVariant[Num[1]];
}
else
{
TFee=CommVariant[Num[1]];
}
}
else
{
if(Hour==CommVariant[Num[1]+2])
{
if(Hour==CommVariant[Num[1]+5])
{
if(Min<CommVariant[Num[1]+1])
{
if(Num[1]==0x00) TFee=CommVariant[Num[0]-2];
else TFee=CommVariant[Num[1]-3];
}
else
{
if(Min<CommVariant[Num[1]+4]) TFee=CommVariant[Num[1]];
//else TFee=CommVariant[Num[1]+3];
}
}
else //Hour<CommVariant[Num[1]+5]
{
if(Min<CommVariant[Num[1]+1])
{
if(Num[1]==0x00) TFee=CommVariant[Num[0]-2];
else TFee = CommVariant[Num[1]-3];
}
else TFee = CommVariant[Num[1]];
}
}
if(Hour<CommVariant[Num[1]+2])
{
if(Num[1]==0x00) TFee=CommVariant[Num[0]-2];
else TFee = CommVariant[Num[1]-3];
}
}
Num[1] += 0x03;
}while((TFee==0x00)&&(Num[1]<Num[0])); //后条件为冗余条件
if(TFee==0x00) TFlag2 = 0x0A5; //冗余代码,时段费率查找失败
if((TFlag1!=0x00)||(TFlag2!=0x00))
{
CommVariant[0] = 0x03; //平: 08:00~22:00
CommVariant[1] = 0x00;
CommVariant[2] = 0x08;
CommVariant[3] = 0x04; //谷: 22:00~08:00
CommVariant[4] = 0x00;
CommVariant[5] = 0x22;
ArrayInit(&CommVariant[6],18);
CommVariant[24] = 0xCE; //校验和
//0x60---时段表1, 0x80---时段表2
Write24C64(CommVariant,0x00,0x60+(Temp[0]&0x01)*0x20,25);
Num[1] = Hour;
TFee = 0x04; //谷费率
if((Num[1]>=0x08)&&(Num[1]<0x22)) TFee=0x03; //平费率
}
//形成费率
if(TFee==0x04) //谷
{
Fee1=1; Fee0=1;
}
else if(TFee==0x03) //平
{
Fee1=1; Fee0=0;
}
else //峰
{
Fee1=0; Fee0=1;
}
Fee_Flag = 0;
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
//**********************************************************
// 名称:RTC参数设置
// 功能:
// 说明:
//**********************************************************
void RTC_Init(void)
{
uchar Temp[2];
//RTC控制寄存器刷新
Temp[0] = 0x23;//00100011:Alarm_W和Alarm_D无效,24小时制,1秒方波输出
RTC_Set(0xE0,Temp,1);
}
//**********************************************************
// 名称:RTC_Set(uchar staddr,uchar idata *ptr,uchar len)
// 功能:RTC设置
// 说明:
//**********************************************************
void RTC_Set(uchar staddr,uchar idata *ptr,uchar len)
{
uchar Temp,Addr[2],Len[2];
Addr[0] = RX_8025; //器件地址
Addr[1] = staddr; //子地址
Len[0] = 0x02; //地址长度
Len[1] = len; //数据长度
Temp = 0;
while(ISendStr(Addr,ptr,Len)==0) //发送数据
{
if(Temp>=32) break; //最多写32次
Temp++;
}
}
//**********************************************************
// 名称:RTC_Read()
// 功能:时间读取
// 说明:
//**********************************************************
void RTC_Read(void)
{
uchar Addr[2],Len[2];
uchar Temp=0;
Addr[0] = RX_8025;
Addr[1] = 0x00;
Len[0] = 0x02;
Len[1] = 0x07;
while(IRcvStr(Addr,RTC,Len)==0) //读取当前时间
{
if(Temp>=32) break; //最多读32次
Temp++;
}
if((TimeCHK(RTC)==0)||(Week>0x06)||(DateCHK(&RTC[4])==0)||(Temp>=0x20)) //时间数据错误
{
////////////////////////////////////////////
SystemCheckFlag |= 0x02; //RTC出错液晶指示
////////////////////////////////////////////
RTCBackPtr &= 0x01;
Read24C64(RTC,0x04,0xE0+RTCBackPtr*8,8);
Temp = ~SumCHK(RTC,7);
if(Temp!=RTCCHK)
{
RTCBackPtr++;
RTCBackPtr &= 0x01;
Read24C64(RTC,0x04,0xE0+RTCBackPtr*8,8);
}
RTC_Init();
RTC_Set(0x00,RTC,0x07);
}
////////////////////////////////////////////
else SystemCheckFlag &= ~0x02; //RTC正常
////////////////////////////////////////////
RTCCHK =~SumCHK(RTC,7); //校验(反码)
}
//**********************************************************
// 名称: RTC_BAK()
// 功能: 时钟缓存备份
// 说明:
//**********************************************************
void RTC_BAK(void)
{
RTCBackPtr++;
RTCBackPtr &= 0x01;
Write24C64(RTC,0x04,0xE0+RTCBackPtr*8,8); //备份时间
}
//**********************************************************
//秒加1
//**********************************************************
void SECINC(void)
{
BCDINC(RTC,1); //Sec加1
RTCCHK = ~SumCHK(RTC,7); //重置检验和
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -