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

📄 measure.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 2 页
字号:
    Write24C64(RevErySavePtr,0x06,0x7E,2);
    //保存整数电量
    Write24C64(&CommVariant[32],0x06,0x00+RevErySavePtr[0]*0x20,17);
  }

}

//***********************************************************************
//名称: ReadRevSaveEry()
//功能: 读取反向(峰、平、谷)整数电量
//说明: 
//***********************************************************************
void ReadRevSaveEry(void)
{
  uchar i,Sum;

  //读取整数电量保存指针
  if(RevErySavePtr[1]!=~RevErySavePtr[0]) //内存指针出错
  {
    Read24C64(RevErySavePtr,0x06,0x7E,2);
    if(RevErySavePtr[1]!=~RevErySavePtr[0]) //Eeprom指针出错
    {
      RevErySavePtr[0] = 0x00;
    }
  }
  //读取整数电量
  for(i=0;i<4;i++)
  {
    RevErySavePtr[0] &= 0x03; //总共4个备份
    Read24C64(&CommVariant[32],0x06,0x00+RevErySavePtr[0]*0x20,17);
    Sum = ~SumCHK(&CommVariant[32],16);
    if(Sum!=CommVariant[48])
    {
      RevErySavePtr[0]++;
    }
    ////////////////////////////////////////////////////////////////
    else if(!BCDCHK(&CommVariant[32+4],16-4)) //保证BCD码加法正确
    {
      RevErySavePtr[0]++;
    }
    ////////////////////////////////////////////////////////////////
    else  break;
  }
  
  //恢复整数电量保存指针
  RevErySavePtr[0] &= 0x03;
  RevErySavePtr[1] = ~RevErySavePtr[0];
}

//***********************************************************************
//名称: CreateRealTimeEry()
//功能: 产生实时电量
//说明: 形成(总/正/反)(总、峰、平、谷)电量
//      CommVariant[00]~CommVariant[15]:总(总、峰、平、谷)电量
//      CommVariant[16]~CommVariant[31]:正(总、峰、平、谷)电量
//      CommVariant[32]~CommVariant[47]:反(总、峰、平、谷)电量
//***********************************************************************
void CreateRealTimeEry(void)
{
  uchar j;

  ArrayInit(CommVariant,16); //清总有功(总、峰、平、谷)电量
  //读取整数电量
  ReadPosSaveEry();
  ArrayInit(&CommVariant[16],4); //清正向总有功电量
  ReadRevSaveEry();
  ArrayInit(&CommVariant[32],4); //清反向总有功电量
  //读取小数电量
  CommVariant[16+4]  = HEX2BCD(Energy.EryTmp1[0]);
  CommVariant[16+8]  = HEX2BCD(Energy.EryTmp1[1]);
  CommVariant[16+12] = HEX2BCD(Energy.EryTmp1[2]);
  CommVariant[32+4]  = HEX2BCD(Energy.EryTmp2[0]);
  CommVariant[32+8]  = HEX2BCD(Energy.EryTmp2[1]);
  CommVariant[32+12] = HEX2BCD(Energy.EryTmp2[2]);
  //计算正向总电量
  BCDAdd(&CommVariant[16],&CommVariant[20],4); //峰
  BCDAdd(&CommVariant[16],&CommVariant[24],4); //峰+平
  BCDAdd(&CommVariant[16],&CommVariant[28],4); //峰+平+谷
  //计算反向总电量
  BCDAdd(&CommVariant[32],&CommVariant[36],4); //峰
  BCDAdd(&CommVariant[32],&CommVariant[40],4); //峰+平
  BCDAdd(&CommVariant[32],&CommVariant[44],4); //峰+平+谷
  //计算总电量
  for(j=0;j<4;j++)
  {
    BCDAdd(&CommVariant[j*4],&CommVariant[16+j*4],4); //+正
    BCDAdd(&CommVariant[j*4],&CommVariant[32+j*4],4); //+反
  }
  //电量翻转处理(5+1)
  for(j=0;j<12;j++)
  {
    CommVariant[j*4+3] &= 0x0F;
  }

}

//**********************************************************
//名称:Write24C64()
//功能:向eeprom写入数据
//说明:ptr--->指向待写数据区首址;  Addr1--->片内高地址
//      Addr1--->片内低地址      ;  DataLen--->数据长度
//      读数据成功时,返回1;否则返回0.
//**********************************************************
bit Write24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen)
{
  uchar i = 0;
  uchar idata *DataPtr;
  uchar idata Addr[3]; //地址数据
  uchar idata Len[2]; //地址空间、数据空间长度
   
  Addr[0] = 0xA0;
  Addr[1] = Addr1;
  Addr[2] = Addr2;
  Len[0]  = 0x03;
  Len[1]  = DataLen;
  DataPtr = ptr;
  
  while(ISendStr(Addr,DataPtr,Len)==0)  
  {
    DataPtr = ptr;
    i++;
    if(i>=32) //最多写32次
    {  
      return(0);
    }
  }
  
  DelayNms(6); //延时6ms
  PowerDownProcess(); //掉电检测处理程序
  return(1);
}

//**********************************************************
//名称:Read24C64()
//功能:读取eeprom中的数据
//说明:ptr--->指向保存数据区首址;  Addr1--->片内高地址
//      Addr1--->片内低地址      ;  DataLen--->数据长度
//      读数据成功时,返回1;否则返回0.
//**********************************************************
bit Read24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen)
{
   uchar i;
   uchar idata *DataPtr;                                    
   uchar idata Addr[3]; //地址数据
   uchar idata Len[2];  //地址空间、数据空间长度
   
   Addr[0] = 0xA0;
   Addr[1] = Addr1;
   Addr[2] = Addr2;
   Len[0]  = 0x03;
   Len[1]  = DataLen;
   DataPtr = ptr;
   i       = 0x00;
   
   while(IRcvStr(Addr,DataPtr,Len)==0)
   {
     DataPtr = ptr;
     i++;
     if(i>=32) //读取EEPROM的数据,最多读32次
     {
       ////////////////////////////////////////
       SystemCheckFlag |= 0x04; //EEPROM出错
       ////////////////////////////////////////
       return(0);
     }
   }
   ////////////////////////////////////////
   SystemCheckFlag &= ~0x04; //EEPROM正常
   ////////////////////////////////////////
   return(1);
}

//***********************************************************************
//名称: PowerDownProcess()
//功能: 
//说明: 掉电检测处理程序
//***********************************************************************
void PowerDownProcess(void)
{
  uchar i,*ptr;
  
  if(ePowerDownCheckFlag==DISABLE) return; //关闭掉电检测
  
  if((CMP1&0x02)==0x00) //前端电压变低
  {
    i = 0xFF;
    while(--i); //延时140uS
    if((CMP1&0x02)==0x00)
    {
      EA = 0;
      LED_F = 1; //峰
      LED_P = 1; //平
      LED_G = 1; //谷
      //保存掉电时间
      Energy.PowerDownTime[0] = Min;
      Energy.PowerDownTime[1] = Hour;
      Energy.PowerDownTime[2] = Day;
      Energy.PowerDownTime[3] = Month;
      Energy.PowerDownTime[4] = Year;
      Energy.TimeCheck        = ~SumCHK(&Energy.PowerDownTime[0],5);
      //本次断电时电能是否反向
      if(REVP==0)  Energy.isRev = 0xAA;
      //RTC备份指针、总反向累计时间备份指针
      Energy.RtcPtr = RTCBackPtr;
      //请在这里添加下电处理事件...
      ptr = &Energy.PulseTmp1[0];
      //if(I2EN == 1)  //I2C总线忙
      //{                   
      I2CON = 0x54;    //STO=1&AA=1 发送停止标志,结束其他I2C操作										
      while(STO == 1);			 			
      //}    									
      I2SCLH = 0x14;   //设置SCL高电平的PCLK周期数
      I2SCLL = 0x14;   //设置SCL低电平的PCLK周期数
      I2CON  = 0x64;   //申请成为主机,起动总线。使用内部SCL发生器,I2EN和AA置位
      while( SI==0 );  //等待起始信号的发送,申请总线
  	         		
      I2DAT = 0xA0;    //发送器件地址
      I2CON = 0x44;    //清除SI位等等
      while( SI==0 );  //等待数据的发送
  	         	
      I2DAT = 0x00;    //发送从地址1
      I2CON = 0x44;    //清除SI位等等
      while( SI==0 );  //等待数据的发送 
    	 
      I2DAT = 0x00;    //发送从地址2
      I2CON = 0x44;    //清除SI位等等
      while( SI==0 );  //等待数据的发送
    	  			
      for(i=0;i<24;i++) //发送数据
      {
        I2DAT = *ptr;
    	I2CON = 0x44;  //清除SI位等等
    	while( SI==0 );
    	ptr++;
      }
      I2CON = 0x54;    //结束总线
      //////////////////////////////////////////////////////////////
      //电源慢上问题
      while((CMP1&0x02)==0x00); //检测上电
      i = 250; //250*40mS=10S
      while(i)
      {
        EA = 0;
        WFEED1 = 0xA5;
        WFEED2 = 0x5A;
        MainMonitor = 0;    //主循环监控变量
        T0Monitor = 0x0000; //Timer0监控变量
        RTCMonitor = 0x0000;//RTC监控变量
        DelayNms(40);       //延时40mS
        if((CMP1&0x02)==0x02)  --i;
        else  AUXR1 |= 0x08;//软件复位
      }
      //////////////////////////////////////////////////////////////
    }
  }
}

⌨️ 快捷键说明

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