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

📄 rtc_dsp.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
    if(i<3)  
    { 
      DspBuf[6] = 0x10;          //LED2
      DspBuf[7] = 0x10;          //LED1(最高位)
      if(i==1)
      {
        DspBuf[4] = 0x10;        //LED4
        DspBuf[5] = 0x10;        //LED3
      }
    }  
  }     		
  //电量相关显示屏
  else if(DspPtr<22) //显示指针10~21
  {
    if(DspPtr<14) //当前总有功(总、峰、平、谷)电量
    {
      CreateRealTimeEry();
      i = (DspPtr-10)*4;
      for(j=0;j<4;j++)  DspExch[j] = CommVariant[i+j];
    }
    else //14~21
    {
      addr1 = 0x01; //上月总有功(总、峰、平、谷)电量
      j = DspPtr-14; 
      if(DspPtr>17)  
      { 
      	addr1 = 0x02; //上月正向有功(总、峰、平、谷)电量
      	j = DspPtr-18;
      }
      i   = LastMonthSN(0); //如果上1月为2月,则i=1
      ////////////////////////////////////////////////////////////////////////////
      if(isLastMonthEry==0x01)  i = LastMonthSN(1); //用上上月电量代替上月电量
      ////////////////////////////////////////////////////////////////////////////
      i <<= 4; //上1月总有功总电量地址
      i += (j<<2);
      //addr2 = i;
      Read24C64(CommVariant,addr1,i,4); //读取历史电量数据
      for(j=0;j<4;j++)  DspExch[j] = CommVariant[j];
    }
    //十万位不处理
    DspBuf[7] = DspExch[3]&0x0F; //万位  :LED1(最高位)	  	 	
    DspBuf[6] = DspExch[2]>>4;   //千位  :LED2
    DspBuf[5] = DspExch[2]&0x0F; //百位  :LED3	
    DspBuf[4] = DspExch[1]>>4;   //十位  :LED4  	  
    DspBuf[3] = DspExch[1]&0x0F; //个位  :LED5    			
    DspBuf[2] = DspExch[0]>>4;   //小数位:LED6(最低位)
  }	
  //系统自检结果显示
  else if(DspPtr==22) //显示指针22
  {
    DspBuf[7] = 0x0E;                 //"E"    :LED1(最高位)
    DspBuf[6] = 0x10;                 //""     :LED2
    DspBuf[5] = 0x10;                 //""     :LED3	
    DspBuf[4] = SystemCheckFlag&0x04; //EEPROM :LED4
    DspBuf[3] = SystemCheckFlag&0x02; //RTC    :LED5    			
    DspBuf[2] = SystemCheckFlag&0x01; //BAT    :LED6(最低位)
  } 		    
  //else if(DspPtr==23) //显示指针23,系统备用
  //{
  //}	        
  //扩展查询显示屏
  else if((DspPtr>25)&&(DspPtr<47)) //显示指针26~46
  {            
    i = 0xC0;  //预置为6个“8”字LED显示: 1100 0000              
    if(DspPtr==26) //时钟偏置
    {
      Read24C64(CommVariant,0x08,0xFE,1);
      DspExch[0] = CommVariant[0];   
      DspExch[2] = DspExch[0];    
      i = 0xCC;  //1100 1100
    }
    else if(DspPtr==27) //全显界面
    {
      DspExch[2] = 0x88;
      DspExch[1] = 0x88;
      DspExch[0] = 0x88;
      //i = 0xC0;	   
    }
    else if((DspPtr==28)||(DspPtr==29)) //时段表切换及标志
    {
      Read24C64(CommVariant,0x09,0x40+(DspPtr-28)*3,3);
      for(j=0;j<3;j++)  DspExch[j] = CommVariant[j];
      //i = 0xC0;
    }
    else if(DspPtr==30) //电量清零次数
    {
      Read24C64(CommVariant,0x05,0xE9,1);
      DspExch[0] = CommVariant[0];
      i = 0xFC; //1111 1100;
    }
    else //时段表1、2时段1~8(30<DspPtr<47)
    {  
      i = DspPtr-30-1; //获取时段N的地址
      j = 0x60+i*3;
      if(DspPtr>38)  
      {
      	i = DspPtr-38-1; //获取时段N的地址
        j = 0x80+i*3;
      }
      Read24C64(CommVariant,0x00,j,3);
      for(j=0;j<3;j++)  DspExch[j] = CommVariant[j];
      
      nFee = DspExch[0]; //暂存时段N费率号
      DspExch[0] = DspExch[1]; //分
      DspExch[1] = DspExch[2]; //时
      DspExch[2] = (i+1)<<4;
      i = 0xD0; //1101 0000;
    }  
    //显示数据拆分  
    DspBuf[2] = DspExch[0]&0x0F; //LED6(最低位)
    DspBuf[3] = DspExch[0]>>4;   //LED5
    DspBuf[4] = DspExch[1]&0x0F; //LED4
    DspBuf[5] = DspExch[1]>>4;   //LED3
    DspBuf[6] = DspExch[2]&0x0F; //LED2
    DspBuf[7] = DspExch[2]>>4;   //LED1(最高位)   
    ///////////////////////////////////////////////////////////////////////////////
    //隐显处理
    for(j=0;j<6;++j)
    {
      if((i>>j)&0x01)  DspBuf[j+2]=0x10;
    }			    			
    ///////////////////////////////////////////////////////////////////////////////   
  } 
  //错误或未用的轮显项处理
  else
  {
    DspPtr = 0x00;
    LCDShowMode = 0; //切换为正常轮显模式
    DspSec  = 0; //显示计数清零
  }
  
  DspBuf[0] = 0;
  DspBuf[1] = 0;	
  for(i=2;i<8;i++)  DspBuf[i] = LcdCoding[DspBuf[i]]; //显示编码转换(LED1~LED6)
  	
  if(EryRev==1)  DspBuf[1] |= 0x02; //反向状态显示
  if(CommLCDSec>0)  DspBuf[1] |= 0x04; //通讯状态显示
  
  //各页固定显示字符形成
  switch(DspPtr)
  {
    case 0x00://当前日期
              DspBuf[0] |= 0x80; //"日期"
	      DspBuf[4] |= 0x10; //P4
    	      DspBuf[6] |= 0x10; //P2	
	      break;			
    case 0x01://当前时间+":"
	      DspBuf[0] |= 0x28;//"时间"+P7
	      DspBuf[1] |= 0x80;//P8
	      DspBuf[4] |= 0x10;//P4
    	      DspBuf[6] |= 0x10;//P2
	      break;
    case 0x02://自动抄表日期
              DspBuf[4] |= 0x10; //P4
              break; 
    case 0x03://资产条形码号(显示前六位)
              DspBuf[0] |= 0x40; //显示“上”
              DspBuf[1] |= 0x20; //显示“局号”
              break; 
    case 0x04://资产条形码号(显示后六位)
              DspBuf[1] |= 0x20; //显示“局号”
              break; 
    case 0x05://屏幕循显时间
              //break; 
    case 0x06://输出脉冲宽度
              //break; 
    case 0x07://电表有功常数
              break; 
    case 0x08://有功反向累计总时间
              DspBuf[0] |= 0x20; //显示“时间”
              DspBuf[1] |= 0x02; //显示“反向”
              break; 
    case 0x09://现在执行时段表编号
              break; 
    case 0x0A:  	
    case 0x0B:
    case 0x0C:
    case 0x0D:
    case 0x0E:
    case 0x0F:
    case 0x10:
    case 0x11:
    case 0x12:
    case 0x13:
    case 0x14:		
    case 0x15://电量数据显示
	      DspBuf[1] |= 0x09; //"电量"+"kW/h"			
	      DspBuf[3] |= 0x10; //小数点--->5P
              if(DspPtr>13)  DspBuf[0] |= 0x02; //显示“上月”
              if(DspPtr==10||DspPtr==14||DspPtr==18)  DspBuf[0] |= 0x01; //显示“总”
              else if(DspPtr==11||DspPtr==15||DspPtr==19)  DspBuf[1] |= 0x10; //显示“峰”
              else if(DspPtr==12||DspPtr==16||DspPtr==20)  DspBuf[0] |= 0x04; //显示“平”
              else DspBuf[1] |= 0x40; //显示“谷”
              break;
    case 0x16://系统自检  
    case 0x1A://时钟偏置
              break;
    case 0x1B://全显界面
              DspBuf[0] = 0xFF;
              DspBuf[1] = 0xFF;
              break;
    case 0x1C://时段切换标志、时、分
              //时段切换日、月、年
              DspBuf[6] |= 0x10; //小数点--->2P
              DspBuf[0] |= 0x68; //时间、上、P7
              DspBuf[4] |= 0x10; //小数点--->4P
              break;    
    case 0x1D://时段切换日、月、年
              DspBuf[6] |= 0x10; //小数点--->2P
              DspBuf[0] |= 0xC0; //日期、上
              DspBuf[4] |= 0x10; //小数点--->4P
              break;
    case 0x1E://电量清零次数
              break;  
      default://时段表1、2时段1~8
              if(DspPtr>38)  DspBuf[0] |= 0x40; //时段表2显示“上”
              if(nFee==2)  DspBuf[1] |= 0x10; //显示“峰”
              if(nFee==3)  DspBuf[0] |= 0x04; //显示“平”
              if(nFee==4)  DspBuf[1] |= 0x40; //显示“谷”
              DspBuf[4] |= 0x10; //小数点--->4P
              DspBuf[1] |= 0x80; //P8
              break;           
  }

  Display(DspBuf); //输送显示数据
  
  /////////////////////////////////////////////////////////////////////////
  /***********************************************************************/
  //刷新I/O口工作模式
  P0M1=0xCF;	//11001111
  P0M2=0xB0;	//10110000
  	  	
  P1M1=0x3F;	//00111111
  P1M2=0xCD;	//11001101
    	
  P2M1=0xFC;	//11111100
  P2M2=0xFF;	//11111111

  P3M1=0x03;	//00000011
  P3M2=0x00;	//00000000
  /***********************************************************************/
  if( ((Prog_Flag)&&(Last_Prog_Flag==0x01)) || (ProgActiveFlag==0xFF) ) //LED编程提示
  {
    ProgLEDShow = ~ProgLEDShow;
    if(ProgLEDShow==0xFF) 
    {
      LED_F = 0; //峰
      LED_P = 0; //平
      LED_G = 0; //谷
    }
    else
    {
      LED_F = 1; //峰
      LED_P = 1; //平
      LED_G = 1; //谷
    } 
  }
  else
  {
    LED_F = 1; //峰指示灯灭
    LED_P = 1; //平指示灯灭
    LED_G = 1; //谷指示灯灭
    if((Fee1==0)&&(Fee0==1))  LED_F = 0; //峰时段指示亮
    else if((Fee1==1)&&(Fee0==1))  LED_G = 0; //谷时段指示亮
    else  LED_P = 0; //平时段指示亮
  }
  ////////////////////////////////////////////////////////////////////////////
}

//**********************************************************
//读取显示控制数据
//**********************************************************   	    	
void DspPara_Read(void)
{
  uchar Temp,CorrectFlag;
	
  CorrectFlag = 0xAA;
  Read24C64(CommVariant,0x00,0x50,6);
  for(Temp=0;Temp<6;Temp++)  DspPara[Temp] = CommVariant[Temp];
  Temp = DspPara[0]+DspPara[1]+DspPara[2];
  //显示数据默认值,必要时可以更改
  if( (DspPara[3]!=~Temp) || ((DspCtrl1==0x00)&&(DspCtrl2==0x00)&&((DspCtrl3&0x3F)==0x00)) )  
  {	
    DspCtrl1    = 0x03;     //当前日期、时间
    DspCtrl2    = 0x34;     //当前总有功(总、平、谷)指数
    DspCtrl3    = 0x00;     //
    DspParaCHK  = 0xC8;     //校验和反码
    CorrectFlag = 0x55;     //重新写入EEPROM
  }
  //轮显时间默认值,必要时可以更改
  if((DspTime!=~DspTimeCHK)||(DspTime==0))
  {
    DspTime     = 0x10;     //10秒,BCD码
    DspTimeCHK  = 0xEF;     //反码校验
    CorrectFlag = 0x55;     //重新写入EEPROM
  }
  //纠正循显参数
  if(CorrectFlag==0x55)  
  {
    for(Temp=0;Temp<6;Temp++)  CommVariant[Temp] = DspPara[Temp];
    Write24C64(CommVariant,0x00,0x50,6);
  }
}

//***********************************************************
// 名称: bit DateTerm(void)
// 功能: 校时期判断(30天判断)
// 说明: 编程禁止时,同一块电表的两次对时操作必须相隔30天以上.
//***********************************************************
bit DateTerm(void)
{
  uchar Temp;
  uchar DataTime[5];
	
  //if(Prog_Flag==1)  return(1); //编程允许时,则校时期允许
  //else 
  //{
    Read24C64(DataTime,0x08,0x7A,5); //读取上次校时时间
    Temp = SumCHK(DataTime,4);
    if(Temp!=~DataTime[4]) //读取最近校时时间发生错误
    {
      return(1); //预置一次广播校时机会
    }    	
    //==================================================
    //月判断
    //==================================================
    Temp 	= BCD2HEX(Month);	 //当前月份
    DataTime[3] = BCD2HEX(DataTime[3]);	 //上次校时月份
    
    if(Temp<DataTime[3]) Temp += 12;	 //跨年
    DataTime[4] = Temp-DataTime[3];	 //计算月差
    
    Temp = 0;                            //预置不进行30日、小时、分比较
    
    if(DataTime[4]>2)  return(1);        //相隔至少3个月,满足校表日期条件
    else if(DataTime[4]==2)              //相隔2个月
    {
      if(DataTime[3]==1)                 //上次校时月份为1月
      {
        Temp = BCD2HEX(Day);	         //当前日期
        DataTime[2] = BCD2HEX(DataTime[2]);//上次校时日期
        if((BCD2HEX(Year)%0x04)==0x00)  Temp += 29; //闰月判断,百年问题不考虑
	else  Temp += 28;
	Temp += 31;
      }
      else  return(1);	                 //上次校时月份不为1月,满足校表日期条件
    } 
    else                                 //相隔0、1个月
    {
      Temp        = BCD2HEX(Day);	 //当前日期
      DataTime[2] = BCD2HEX(DataTime[2]);//上次校时日期

      if(DataTime[4]==1)                 //相隔1个月
      {
      	//上次校时月份为2月
	if( DataTime[3]==2 ) 
	{
	  if((BCD2HEX(Year)%0x04)==0x00)  Temp += 29; //闰月判断,百年问题不考虑
	  else  Temp += 28;			
	}	
	//上次校时月份为4、6、9、11月			
	else if(DataTime[3]==4||DataTime[3]==6||DataTime[3]==9||DataTime[3]==11) Temp += 30;	
	//上次校时月份为1、3、5、7、8、10、12月									
	else Temp += 31;
      }
      //else  Temp = BCD2HEX(Day);	 //Temp即为当前日期
    }				
		
    if(Temp>DataTime[2])
    {
      Temp -= DataTime[2];
      //校时限制天数(30天)判断	    	
      if(Temp>DateErrorTerm)  return(1);	
      else if(Temp==DateErrorTerm)//天数相等
      {	
        //小时、分比较
        if((Hour>DataTime[1])||((Hour==DataTime[1])&&(Min>=DataTime[0])))  return(1);//5分钟有效 		
        else return(0);
      }
      else return(0);
    }
    else
    {
      return(0);  
    }  
  //}
}

//**********************************************************
// 名称: Ery_Balance()
// 功能: 电量结算处理,电表管理状态切换处理
// 说明:
//**********************************************************
void Ery_Balance(void)
{
  uchar j,Temp,vTemp;
  uchar TMonth[2];
  uchar TBalance;
	
  //读取上次结算月份
  CurrentMonthNoBlnFlag = 0x00;
  isLastMonthEry = 0x00;
  TBalance = BlnDateCheck(0x8B); //电能结算日期判断
  ////////////////////////////////////
  if(TBalance>12)  TBalance = 0x00;
  ////////////////////////////////////
  if(TBalance>0x00)
  { //////////////////////////////////////////////////////////////////////
    ePowerDownCheckFlag = DISABLE; //关闭掉电检测
    //////////////////////////////////////////////////////////////////////
    //判断当前月是否进行电能结算
    vTemp = 0x00;
    TMonth[0] = BCD2HEX(Month); //当前月份HEX数据
    if(CurrentMonthNoBlnFlag==0x01)
    {	
      vTemp = 0x01; //本月结算日未到,不结算
      if(TMonth[0]==1)  TMonth[0] = 12;
      else  TMonth[0]--;
      CurrentMonthNoBlnFlag = 0x00;
    }
    //形成(总/正/反)(总、峰、平、谷)电量
    CreateRealTimeEry();
    //保存历史电量,反向历史事件
    for(j=0;j<3;j++)
    {
      for(Temp=vTemp;Temp<TBalance;Temp++)
      { 
        Write24C64(&CommVariant[j*16],j+1,LastMonthSN(Temp)<<4,16);
      }
    }
    //读取当前月反向累计时间、最后一次反向起、止时间
    Read24C64(CommVariant,0x04,0xC0,16);
    //写本次结算形成的上几个月的反向历史电量事件
    for(Temp=vTemp;Temp<TBalance;Temp++)
    {
      Write24C64(CommVariant,0x04,LastMonthSN(Temp)<<4,16);
    }
    //清除当前月反向累计时间、最后一次反向起、止时间
    if(vTemp==0)
    {
      ArrayInit(CommVariant,16);
      EryRev = 0;
      Write24C64(CommVariant,0x04,0xC0,16);
    }
    //写本次结算月份,为下次结算作参考
    TMonth[1] = ~TMonth[0];
    Write24C64(TMonth,0x08,0x8B,2);
    //////////////////////////////////////////////////////////////////////
    ePowerDownCheckFlag = ENABLE; //打开掉电检测
    //////////////////////////////////////////////////////////////////////
  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -