⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtc_dsp.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
  
  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 + -