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

📄 rtc_dsp.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:

//**********************************************************
//读取温度值
//**********************************************************
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 + -