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

📄 rtc_dsp.c

📁 本代码为电子式单相多费率电能表的源程序
💻 C
📖 第 1 页 / 共 4 页
字号:
#include <Reg936.h>
#include <Meter_def.h>
#include <General.h>
#include <var.h>

//**********************************************************
//函数申明
//**********************************************************
void  RTC_Dsp_Proc(void);	        //时间、显示事件处理
void  BatWorkState_Proc(void);          //电池工作状态处理
void  KBG_Even_Proc(void);              //开表盖事件处理
void  KDNH_Even_Proc(void);             //开端钮盒事件处理
void  Dsp_Proc(void);		        //显示处理
void  Rev_Even_Proc(void);		//电能反向事件处理
void  DspPara_Read(void);	        //读显示控制参数
void  Ery_Balance(void);	        //电量冻结
void  Temp_Equalize(void);	        //时钟温度补偿
void  Fee_CHK(void);		        //费率检查和切换
void  MeterStateChange(void);           //电表在新进状态时,连续运行36小时后自动切换至运行状态
                                        
void  RTC_Init(void);		        //RTC初始化设置
void  RTC_Read(void);		        //时间读取
void  RTC_BAK(void);		        //时间备份
void  SECINC(void);                     //秒加1

void  Display(uchar idata *ptr);	//LCD数据刷新
void  RTC_Set(uchar staddr,uchar idata *ptr,uchar len);	//RTC设置

 bit  DateTerm(void);			//日期条件判断
 bit  DateCHK(uchar idata *ptr);	//日期正确性判断
 bit  TimeCHK(uchar idata *ptr);	//时间正确性判断
uchar pt(uchar year,uchar month);       //
long int DateDifferenceCal(uchar idata *pDate1,uchar idata *pDate2);//日期时间差计算
 
uchar Temp_Read(void);		        //温度测量
uchar LastMonthSN(uchar sn);		//历史月份计算
uchar BlnDateCheck(uchar addr2);	//电能结算日期判断

//**********************************************************
//函数外部引用
//**********************************************************
extern void  CreateRealTimeEry(void);
extern void  PowerDownProcess(void);
extern bit   Write24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
extern bit   Read24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);

//**********************************************************
// 名称: RTC_Dsp_Proc()
// 功能: 时钟、显示处理
// 说明:
//**********************************************************
void RTC_Dsp_Proc(void)									
{	  	
  Watchdog_feed(); //喂狗
  //费率检查
  if((Fee0==0)&&(Fee1==0))  
  {
    Fee_Flag = 1; //置位费率检查标志
  } 
  //显示方式检查
  if( (DspParaCHK!=~(DspPara[0]+DspPara[1]+DspPara[2]))||(DspTime!=~DspTimeCHK)||(DspDataReadFlag==1) )
  {
    DspDataReadFlag = 0;
    DspPara_Read(); //显示控制参数校对处理
  }
  //显示刷新
  if(DspFlag==1) //显示刷新标志位(1秒刷新一次)
  {	      
    DspFlag = 0; //清除显示刷新标志位
    //※※※※※※※※※※※※※※※※※※※※※※※※※※※※※  		
    if(Sec>=0x59) //整分时刻任务事件处理
    {
      RTC_Read(); //1分钟间隔校时
      if(Sec<=0x02) //3秒时间窗口
      {
        if(Min&0x01)  RTC_BAK(); //逢单时间备份(2分钟备份一次)
	//AdjDate = DateTerm();  //日期条件检查
	if(((Min==0x00)||(Min==0x30))) //半小时间隔判断检查
	{	
	  Fee_Flag = 1; //时段费率检查标志位
	  RTC_Init(); //时钟配置初始化(刷新)	
	  if(Min==0x00)	//整点时刻任务处理
	  {
	    EryBln_Flag = 1; //电量冻结计算标志
	    Temp_Equalize(); //1小时时钟温度补偿
	  }
	}
      }
    }
    else  SECINC(); //秒加1
    //※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
    ////////////////////////////////////////////////////////////
    KBG_Even_Proc();  //开表盖事件处理
    KDNH_Even_Proc(); //开端钮盒事件处理
    Rev_Even_Proc();  //电能反向事件处理
    ////////////////////////////////////////////////////////////
    Dsp_Proc(); //显示处理
  }
  
  //监控主循环是否正常运行
  MainMonitor = 0;
  //监控Timer0是否正常运行
  T0Monitor++;
  if(T0Monitor>1000)  AUXR1 |= 0x08; //软件复位
  //保证外部中断1正常运行
  EX1   = 0;
  IT1   = 1;
  IP0H |= 0x04;
  IP0  &=~0x04;
  EX1   = 1;
  CMP1  = 0x38;
  CMP2  = 0x38;
  //未用功能模块关闭
  PCONA   = 0x55; //0101 0101
  //关闭未用之中断
  EC  = 0;  //关比较器中断
  EX0 = 0;  //关闭外部中断0
  EST = 0;  //关闭TX发送中断
  EBO = 0;  //关闭掉电检测中断
  EI2C = 0; //关闭I2C中断
  ESPI = 0; //关闭SPI模块
  SPCTL = 0x84;
  
  //////////////////////////////////////////////////////////////
  if(CommFlag==0) //不在通讯状态
  {
    HW38K   = 1;
    if(COMMSEL==0) //默认红外通讯
    {
      KBPATN  = 0xFF;
      KBCON   = 0x00; //PATN_SEL=0
      KBMASK  = 0x40; //打开RS485通讯唤醒			
      IP1    &=~0x02; //中断优先级为0级(最低)
      IP1H   &=~0x02;                                
      EKBI    = 1;    //键盘中断使能
    }
  }
  if((CommFlag==1)&&(ES==0)) //串口异常
  {
    ReinitUARTFlag = 1; //UART重新初始化标志
  }
  //////////////////////////////////////////////////////////////
  if(Fee_Flag==1)
  {
    Fee_CHK(); //时段费率处理
  }
  if(EryBln_Flag==1)
  {
    Ery_Balance(); //结算日处理(日、时)
    MeterStateChange(); //电表在新进状态时,连续运行36小时后自动切换至运行状态
  }
  
  //////////////////////////////////////////////
  ePowerDownCheckFlag = ENABLE; //打开掉电检测
  //////////////////////////////////////////////
  PowerDownProcess(); //掉电检测处理程序
}

//**********************************************************
// 名称: void BatWorkState_Proc(void)
// 功能: 
// 说明: 电池工作状态处理
//**********************************************************
void BatWorkState_Proc(void)
{
  long int BatWorkTime1,BatWorkTime2;
  uchar Temp;
    
  Watchdog_feed(); //喂狗
  
  ///////////////////////////////////////////////////////////////////////////
  //上次断电时电能反向处理(电能反向终止事件是否发生)
  Read24C64(CommVariant,0x00,0x16,1); //上次断电前电能是否反向标志
  if(CommVariant[0]==0xAA) //发生电能反向终止事件
  {
    Read24C64(CommVariant,0x00,0x10,4); //读取上次系统掉电时间
    Write24C64(CommVariant,0x04,0xC7,4); //写发生电能反向终止事件时间
  }
  ///////////////////////////////////////////////////////////////////////////
  
  //读取上次断电时电池工作状态
  Read24C64(CommVariant,0x00,0xEA,2); //电池工作状态+校验
  if(CommVariant[0]!=~CommVariant[1])
  {
    CommVariant[0] = 0x00; //默认为电池处于欠压状态
    CommVariant[1] = 0xFF;
  }
  if(CMP2&0x02) //电池电压高
  {
    //Battery = 0x00; //电池不工作
    if(CommVariant[0]==0x00)  BatUpFlag = 0x01; //电池上电标志
    else  Battery = 0x01; //电池有效工作
    MeterRunFlag &= 0xFB; //电池电压正常
    CommVariant[0] = 0xAA;
    CommVariant[1] = 0x55;
  }
  else //电池电压低
  {
    //Battery = 0x00; //电池不工作
    if(CommVariant[0]==0xAA)  BatAlert = 0x01; //电池报警标志
    ////////////////////////////////////////////
    MeterRunFlag |= 0x04;    //电池欠压
    SystemCheckFlag |= 0x01; //电池欠压液晶指示
    ////////////////////////////////////////////
    CommVariant[0] = 0x00;
    CommVariant[1] = 0xFF;
  }
  //回写电池工作状态
  Write24C64(CommVariant,0x00,0xEA,2);
  //读取当前时间
  RTC_Read();
  CommVariant[10] = RTC[1]; //Min
  CommVariant[11] = RTC[2]; //Hour
  CommVariant[12] = RTC[4]; //Day
  CommVariant[13] = RTC[5]; //Month
  CommVariant[14] = RTC[6]; //Year
  CommVariant[15] = ~SumCHK(&CommVariant[5],5);
    
  if(Battery) //电池处于有效工作状态
  {
    Read24C64(CommVariant,0x00,0x10,6); //读取上次系统掉电时间
    CommVariant[6] = ~SumCHK(CommVariant,5);
    if(CommVariant[5]!=CommVariant[6])
    {
      CommVariant[4] = Year;   //年
      CommVariant[3] = Month;  //月
      CommVariant[2] = Day;    //日
      CommVariant[1] = Hour;   //时
      CommVariant[0] = Min;    //分
    }
    //返回本次上电与上次下电之工作时间(分钟)
    BatWorkTime1 = DateDifferenceCal(&CommVariant[2],&CommVariant[12]); //计算相差天数
    BatWorkTime1 = BatWorkTime1*24*60 + BCD2HEX(CommVariant[11])*60 + BCD2HEX(CommVariant[10]);
    BatWorkTime2 = BatWorkTime1 - BCD2HEX(CommVariant[1])*60 - BCD2HEX(CommVariant[0]);
    //读取电池工作时间
    Read24C64(CommVariant,0x00,0xE6,4); //电池工作时间+校验
    Temp = CommVariant[0]+CommVariant[1]+CommVariant[2];
    if(CommVariant[3]!=~Temp)  ArrayInit(CommVariant,4); //清零
    //电池工作时间累加
    BatWorkTime1  = BCD2HEX(CommVariant[2])*10000+BCD2HEX(CommVariant[1])*100+BCD2HEX(CommVariant[0]);
    BatWorkTime2 += BatWorkTime1;
    //以BCD码形式保存数据
    Temp = (uchar)(BatWorkTime2/10000);
    CommVariant[2] = HEX2BCD(Temp);
    BatWorkTime2 = BatWorkTime2%10000;
    Temp = (uchar)(BatWorkTime2/100);
    CommVariant[1] = HEX2BCD(Temp);
    Temp = (uchar)(BatWorkTime2%100);
    CommVariant[0] = HEX2BCD(Temp);
    CommVariant[3] = ~(CommVariant[0]+CommVariant[1]+CommVariant[2]);
    //回写电池工作时间
    Write24C64(CommVariant,0x00,0xE6,4);
  }

  if(BatAlert) //电池报警
  {
    Write24C64(&CommVariant[10],0x00,0xE0,6); //电池报警+校验
  }
  
  if(BatUpFlag) //电池上电
  {
    ArrayInit(CommVariant,10);
    Write24C64(CommVariant,0x00,0xE0,10); //电池相关数据清零
  }
  
  //////////////////////////////////////////////
  ePowerDownCheckFlag = ENABLE; //打开掉电检测
  //////////////////////////////////////////////
  PowerDownProcess(); //掉电检测处理程序 
}

//**********************************************************
// 名称: Rev_Even_Proc()
// 功能: 
// 说明: 电能反向事件处理
//**********************************************************
void Rev_Even_Proc(void)
{ 
  uchar Temp=0;
  
  //电能反向事件监测	
  if(REVP==0)
  {
    RevDeLayTimer++;
  }
  else
  {
    RevSec = 0x00;
    RevDeLayTimer = 0x00; 
    //////////////////////////////////////////////////
    MeterRunFlag &= 0xEF;
    //////////////////////////////////////////////////
    if(EryRev==1)  Temp = 0xC7; //电能反向终止事件判断
    EryRev = 0; //电能反向标志清零
  }
  //电能反向开始事件判断
  if(RevDeLayTimer>3)
  {
    //////////////////////////////////////////////////
    MeterRunFlag |= 0x10;
    //////////////////////////////////////////////////
    if(EryRev==0)  Temp = 0xC3; //发生电能反向起始事件                 	
    EryRev = 1; //电能反向标志置位
  }
  //写当前月最后一次反向起/止时间
  if(Temp>0)
  {
    CommVariant[0] = Min;  //分
    CommVariant[1] = Hour; //时
    CommVariant[2] = Day;  //日
    CommVariant[3] = Month;//月
    Write24C64(CommVariant,0x04,Temp,4);
  }
  //电能反向累计总时间计算
  if(EryRev==1)  RevSec++;
  if(RevSec>59)	//反向时间累计满1分钟处理
  {
    RevSec  = 0x00;
    for(Temp=0;Temp<2;Temp++)
    {
      Read24C64(CommVariant,0x04,0xC0+Temp*0x10,3);
      //0xD0--->有功反向累计总时间
      //0xC0--->当前月总反向累计时间
      BCDINC(CommVariant,3); //+1
      Write24C64(CommVariant,0x04,0xC0+Temp*0x10,3); //回写
    }
  }
  
}

//**********************************************************
// 名称: Dsp_Proc()
// 功能: 
// 说明: 液晶显示处理
//**********************************************************
void Dsp_Proc(void)
{ 	
  uchar i,j,addr1,nFee;
  uchar DspBuf[8]; //显示缓冲区

  DspSec++; //轮显时间+1
  if(CommLCDSec>0)  CommLCDSec--; //液晶通讯指示显示时间-1

  if(LCDShowMode==1) //液晶显示屏查看模式
  {
    if(LCDViewSec==0)
    {
      DspPtr = 0x00;
      LCDShowMode = 0; //查询结束,切换为正常轮显模式
      DspSec  = 0; //显示计数清零
    }
    else  --LCDViewSec; //液晶显示屏查看时间-1
  }
  
  if(LCDShowMode==0) //正常轮显模式
  {
    //显示项目切换
    if( (DspSec>=BCD2HEX(DspTime)) || (ProgActiveFlag==0xFF) ) //轮显时间满或者按键轮显,更新显示指针
    { 
      DspSec  = 0; //显示计数清零
      DspCtrl3 &= 0x3F; //屏蔽DspPtr=(22、23);
      if((SystemCheckFlag&0x07)!=0)  DspCtrl3 |= 0x40; //DspPtr=22
      else  DspCtrl3 &= ~0x40;
      
      i = 0x00; //轮显指针处理
      do
      {
        DspPtr++;
        if(DspPtr<8)  i = (DspCtrl1>>DspPtr)&0x01; //第一显示控制字节判断(0~7)
        	
        else if(DspPtr>15) //第三显示控制字节判断(16~21)
        {
          i = (DspCtrl3>>(DspPtr-16))&0x01;		
          if(DspPtr>=23)  DspPtr = 0xFF; //显示项判断结束
        }
        
        else  i = (DspCtrl2>>(DspPtr-8))&0x01; //第三显示控制字节判断(8~15)
        
      } while(i==0x00);
    }
  }
  
  //各页变量数据形成
  if(DspPtr<10) //显示指针0~9
  {            
    i = 3;  //预置为6个“8”字LED显示                 
    if(DspPtr==0) //当前日期显示         
    {
      DspExch[2] = Year;
      DspExch[1] = Month;
      DspExch[0] = Day;  
      //i = 3;
    }
    else if(DspPtr==1) //当前时间显示
    {
      DspExch[2] = Hour;
      DspExch[1] = Min;
      DspExch[0] = Sec;
      //i = 3;
    }
    else if(DspPtr==2) //自动抄表日期
    {
      Read24C64(CommVariant,0x08,0x88,2);
      for(j=0;j<2;j++)  DspExch[j] = CommVariant[j];
      i = 2;
    }
    else if((DspPtr==3)||(DspPtr==4)) //资产条形码号:显示高六位--->3 ; 显示低六位--->4 .
    { //电表局号高6位
      i = 3;
      if(DspPtr==4)  i = 0;
      Read24C64(CommVariant,0x00,0xF7+i,3);
      for(j=0;j<3;j++)  DspExch[j] = CommVariant[j];
      i = 3;
    }
    else if(DspPtr==5) //屏幕循显时间
    {
      DspExch[0] = DspTime;
      i = 1;
    }
    else if(DspPtr==6) //输出脉冲宽度:80mS
    {
      DspExch[0] = 0x80;
      DspExch[1] = 0x00;
      i = 2;
    }
    else if(DspPtr==7) //电表有功常数:1600imp/kWh
    {
      DspExch[0] = 0x00;
      DspExch[1] = 0x16;
      i = 2;	
    }
    else if(DspPtr==8) //有功反向累计总时间
    {
      Read24C64(CommVariant,0x04,0xD0,3);
      for(j=0;j<3;j++)  DspExch[j] = CommVariant[j];
      //i = 3;
    }
    else //现在执行时段表编号
    {
      Read24C64(CommVariant,0x09,0x4F,1);
      DspExch[0] = CommVariant[0];
      DspExch[0] += 1;
      i = 1;
    }   
    //显示数据拆分  
    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(最高位)   

⌨️ 快捷键说明

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