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

📄 measure.c

📁 著名的CS5463抄表模块
💻 C
📖 第 1 页 / 共 4 页
字号:

/**************************************************************
Copyright(C) 2007,Huaruijie Co.Ltd.
文件名:	Measure.c
版权:华瑞杰公司 2007
作者: 开发部 	zhw  
描述: 计量统计分析任务

文件记录:
1. 2007-02-06 zhw <Create> 
*/

#include "includes.h"

#include "basetype.h"
#include "DrvCfg.h"
#include "cs5463.h"
#include "HRJ803.h"
#include "driver.h"
#include "Pulse.h"
#include "db.h"
#include "UartDrv.h"
//extern const SSysParam *p_gcSysParam;	//use for compute data item offset address

//#define DEBUG 
//#define DEBUG_SUM
//#define DEBUG_MAIN
//#define DEBUG_INIT
// #define  DEBUG_RATE_ENERGY
//#define DEBUG_MAXDEMAND_SUM
//#define DEBUG_MAXDEMAND_RATIO
//#define DEBUG_MAXDEMAND_SUM_DAY
/**********************以下为计量统计所用到的结构*******************/

#define  MAX_Sliding_NUM   16  //最大的滑差次数  ( 60min/4min )+1


#define MAX_DEMAND_TYPE_NUM 8 //总的最大需量类型数 ,dwSum
enum eMaxDemandType{eEMaxPp,eEMaxPn,eEMaxQp,eEMaxQn,
	                eEMaxQ1,eEMaxQ2,eEMaxQ3,eEMaxQ4
	};
    /*  需量类型包括: (不分费率)
		正向有功最大需量、反向有功最大需量、
		正向无功最大需量 、反向无功最大需量 、
		一象限无功最大需量 、二象限无功最大需量、
		三象限无功最大需量 、四象限无功最大需量
	*/
enum eEnergyType{eEPp, eEPap,eEPbp,eEPcp,
	             eEPn, eEPan,eEPbn,eEPcn,
	             eEQ1, eEQ2, eEQ3, eEQ4,
	             eEQap,eEQbp,eEQcp,eEQan,
	             eEQbn,eEQcn
	};
/*电能类型  不分费率(即总的)
正向总有功电能   
A相正向有功电能  
B相正向有功电能  
C相正向有功电能  
                 
反向总有功电能   
A相反向有功电能  
B相反向有功电能  
C相反向有功电能 

一象限总无功电能 
二象限总无功电能 
三象限总无功电能 
四象限总无功电能 

A相正向无功电能 
B相正向无功电能 
C相正向无功电能 
A相反向无功电能 
B相反向无功电能 
C相反向无功电能 
*/
typedef struct 
{
    DWORD dwSlidingCnt[MAX_DEMAND_TYPE_NUM][MAX_Sliding_NUM];	//滑差时刻点对应的g_sEneryCnt
    BYTE byCurCntStartIndex; //FIFO的开始索引
    BYTE byCurCntEndIndex;   //FIFO的结束索引
}SSlidingStat; /*滑差统计结构*/

typedef struct 
{
    DWORD dwSlidingCnt[2][MAX_Sliding_NUM];	//滑差时刻点对应的g_sEneryCnt
    BYTE byCurCntStartIndex; //FIFO的开始索引
    BYTE byCurCntEndIndex;   //FIFO的结束索引
}SSlidingStat_Day; /*日统计的滑差统计结构*/

typedef struct //计量任务用到的统计结构
{
	SDateTime sCurDateTime;  //当前时刻
    SDateTime sLastDateTime;  //当前时刻
    DWORD dwCurTick;//当前时刻对应的Tick
	BYTE byCurRationNo; //当前时刻对应的费率号
    
	// 用来计算费率(尖、峰、平、谷)的最大需量
	SDateTime sCurSlidingTime;//本次滑差开始时刻   
    DWORD dwCurSlidingTick;//本次滑差开始时刻对应的Tick
	BYTE byCurSlidingRatioNo; // 本次滑差开始时刻对应的费率号
    BYTE  byCurRatioSlidingNum; //经过的滑差次数
    SSlidingStat sRatioSliding; //滑差统计结构,

    //用来计算总的最大需量
    //SDateTime sSumSlidingTime; //本次滑差开始时刻
    DWORD dwSumSlidingTick;//本次滑差开始时刻对应的Tick
    BYTE  byCurSumSlidingNum; // 经过的滑差次数
    SSlidingStat sSumSliding;  //滑差统计结构
    
  	//用来计算日统计的有功最大需量 无功最大需量  
   // SDateTime sDaySumSlidingTime; //本次滑差开始时刻
    DWORD dwDaySumSlidingTick;//本次滑差开始时刻对应的Tick
    BYTE  byDayCurSumSlidingNum; // 经过的滑差次数
    SSlidingStat_Day  sDaySumSliding;//日统计对应的滑差结构
     
    BYTE  bySlidingNum;//滑差次数
    BYTE byDemandStateEnd;  //需量周期结束标志,1结束,0未结束
	SEnergyCnt sLastEneryCnt;//上次脉冲更新时的计数脉冲数 。add zhw 2007-02-08
	SEnergy sLastEnergy;   //上次脉冲更新时的能量 。add zhw 2007-02-08
	DWORD dwEnergyOutPut[6]; //已经通过脉冲输出的能量值,分别为P+,P-,Q+,Q-,PLED,QLED
	BYTE bySaveFlag; //保存电量的标志
	STime4 sLastTime4;

}SMeasureStat; 




/*统计任务流程:
     1)初始化 电能量文件 、 需量文件、 电表参数文件.	    
	    SMeasureStat 结构初始化  细化 有功电能起始读数,无功电能起始读数
     2)判断数据就绪, 
	      比较sEneryCnt与g_sEneryCnt的有变化的量,
	    根据当前时刻的费率,做相应的处理,结果放入到电能量文件
	     
	      判断g_sEneryCnt中有变化的成员,根据当前时刻的费率号,保存到相应的g_sEnergy中,
	 3)针对总的最大需量统计(总最大需量)
		 当前时刻(sCurDateTime)与本次滑差开始时刻(sSumSlidingTime),间隔是否大于等于一个滑差时间
	        若是,则本次滑差开始时刻(sSumSlidingTime)=当前时刻 (为下次判断准备),
		         byCurSumSlidingNum++,
                 循环i,MAX_DEMAND_TYPE_NUM次 使得sSumSliding[i][byCurCntEndIndex] = 改需量对应的电能值
				 sSumSliding.byCurCntEndIndex加一,等于MAX_Sliding_NUM则置0;
		         判断byCurSumSlidingNum是否大于等于滑差数,
		            若是,则根据byCurCntStartIndex, byCurCntEndIndex,dwSlidingEntergy[][],
					    循环 计算各项最大需量,并与当前的最大需量比较获得最新的最大需量;
			            sSumSliding.byCurCntStartIndex加一,等于MAX_Sliding_NUM则置0;
			    byCurRatioSlidingNum等于滑差数(为下次判断准备,保证byCurRatioSlidingNum不大于 滑差数+1)
         
	 4)针对费率号的最大需量统计(尖、峰、平、谷)
	     当前时刻(sCurDateTime) 与 本次滑差开始时刻(sCurSlidingTime),间隔是否大于等于一个滑差时间
	        若是,则本次滑差开始时刻=当前时刻 为下次判断准备),byCurRatioSlidingNum++,
			     循环i,MAX_DEMAND_TYPE_NUM次 使得sRatioSliding[i][byCurCntEndIndex] = 改需量对应的电能值
				 sRatioSliding.byCurCntEndIndex加一,等于MAX_Sliding_NUM则置0;
		         判断byCurRatioSlidingNum是否大于等于滑差数,
		            若是,则根据byCurCntStartIndex, byCurCntEndIndex,dwSlidingEntergy[][],
					    循环 计算各项最大需量,并与当前的最大需量比较获得最新的最大需量;
			            sRatioSliding.byCurCntStartIndex加一,等于MAX_Sliding_NUM则置0;
					    byCurRatioSlidingNum等于滑差数(为下次判断准备,保证byCurRatioSlidingNum不大于 滑差数+1)
        当前时刻对应的费率号(buCurRationNo)与 本次滑差开始时刻对应的费率号(byCurSlidingRatioNo)是否一致,
		     若不一致则 本次滑差开始时刻=本次循环的时刻,byCurCntStartIndex=0,byCurCntEndIndex=0
			           byCurSlidingRatioNo=buCurRationNo,byCurRatioSlidingNum=0。
	 5)如果是5/10/15/30/60整数(整数倍时间间隔的电量数据)
     6)如果当前时刻是抄表日的时刻,
	        若是 则保存电能数据,保存需量数据。当前最大需量清零。
	             对一些数据重新赋值,滑差开始时刻=本次循环的时刻,byCurCntStartIndex=0,byCurCntEndIndex=0
			     byCurSlidingRatioNo=buCurRationNo,byCurRatioSlidingNum=0。
	 7) LED及脉冲处理   1600
      2)3)4)5)6)循环
*/
extern DWORD MeasureTaskStack[];
extern DWORD VoltageTaskStack[];
extern DWORD DispTaskStack[];
extern DWORD OS_STK_RS485A[];
extern DWORD OS_STK_INFRARED[];

static BYTE BCD2BIN(BYTE a) 
{
	return(((a)>>4)*10 + ((a) & 0x0f));
}
static BYTE BIN2BCD(BYTE a)
{
	return((((a)/10) << 4) | ((a)%10));
}

/****本文件用到的局部变量的定义区,******/
//闰年的天数  2月份为29天 见HRJ803.h
const  WORD w_Ration_jdays[12] = {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335};

//获得指定时刻的费率
static void GetCurRateNo(SDateTime *psCurDateTime,BYTE *pRatioNo,SMeterParam *psMeterParam)
{
	BYTE i;
	BYTE j;
	BYTE byCurIndex;
	BYTE byMonth;
	BYTE byDay;
    WORD wPretemp;
	WORD wNexttemp;
	WORD wCurtemp;
	i = psCurDateTime->byHour ;
    j = (psCurDateTime->byMinute >=30 ? 1:0); 
 //   *pRatioNo = psMeterParam->byTimeTable[0][i];
    *pRatioNo  = (j==0) ? (psMeterParam->byTimeTable[0][i] & 0x0f) : ((psMeterParam->byTimeTable[0][i] & 0xf0)>>4);
	if(*pRatioNo >3)
	{
		//Print("9999");
		*pRatioNo =0;
    }
	/*
    wPos = w_Ration_jdays[byMonth-1] + byDay -1;
	byFlag = 0;
	j = BCD2BIN(psMeterParam->byYearZoneNum );
	for(i=0; i<j-1 ; i++)
	{
		byMonth = BCD2BIN(psMeterParam->sYearZoneTable[i].byStartMonth);
		byDay = BCD2BIN(psMeterParam->sYearZoneTable[i].byStartDay);
        wPretemp = w_Ration_jdays[byMonth-1] + byDay;
		byMonth = BCD2BIN(psMeterParam->sYearZoneTable[i+1].byStartMonth);
		byDay = BCD2BIN(psMeterParam->sYearZoneTable[i+1].byStartDay);
		wNexttemp =  w_Ration_jdays[byMonth-1] + byDay;

        wCurtemp = w_Ration_jdays[psCurDateTime->byMonth-1] + psCurDateTime->byDay;
		if(wCurtemp <wNexttemp  && wCurtemp >=wPretemp)
	    {
		   byFlag = 1;
		   break;
        }
	}
	if(byFlag ==0)
	{
		i = BCD2BIN(psMeterParam->byYearZoneNum)-1;
	}
	byCurIndex = BCD2BIN(psMeterParam->sYearZoneTable[i].byDayTableNo) -1;
	if(byCurIndex >BCD2BIN(psMeterParam->byTimeTableNUm) -1 //防止越限的发生
	   byCurIndex =0;

	for(i=0; i<psMeterParam->byDayPeriodOfTime; i++)  //日时段(每日切换数)m  每个表的每日切换数都一定时m个吗?
	{
		//if(psMeterParam->sDayTimeTable[byCurIndex][i].byStartHour > 23)
               
        wPretemp =  BCD2BIN(psMeterParam->sDayTimeTable[byCurIndex][i].byStartHour) *
                    BCD2BIN(psMeterParam->sDayTimeTable[byCurIndex][i].byStartMin);
        wNexttemp = BCD2BIN(psMeterParam->sDayTimeTable[byCurIndex][i].byStartHour) *
                    BCD2BIN(psMeterParam->sDayTimeTable[byCurIndex][i].byStartMin);
        wCurtemp =  BCD2BIN(sCurDateTime->byHour) * BCD2BIN(sCurDateTime->byMinute);
	    if(wCurtemp <wNexttemp  && wCurtemp >=wPretemp)
	    {
           byFlag = 1;
		   break;
        }
	}
	if(byFlag ==0)
	{
       i = BCD2BIN(psMeterParam->byYearZoneNum) -1;
	}
    *pRatioNo = BCD2BIN(psMeterParam->sDayTimeTable[byCurIndex][i].byRateNo);
    if(*pRatioNo >3)
	{
		//Print("9999");
		*pRatioNo =0;
    }
	*/
}
/**************初始化计量统计结构*******/
static void InitMeasureStat(BYTE byFlag,SMeasureStat *psMeasureStat,SMeterParam *psMeterParam)
{
	BYTE i;
	BYTE j;
	DWORD dwTemp;
	GetTime(&psMeasureStat->sCurDateTime);
	GetTime(&psMeasureStat->sLastDateTime);
 	GetTime(&psMeasureStat->sCurSlidingTime);
    GetCurRateNo(&psMeasureStat->sCurDateTime,&psMeasureStat->byCurRationNo,psMeterParam);
	GetCurRateNo(&psMeasureStat->sCurSlidingTime,&psMeasureStat->byCurSlidingRatioNo,psMeterParam);
   
  // GetTime(&psMeasureStat->sSumSlidingTime);//本次滑差开始时刻;用来计算总的最大需量,
	psMeasureStat->dwCurTick =OSTimeGet();
    psMeasureStat->dwCurSlidingTick = psMeasureStat->dwCurTick;
    psMeasureStat->dwSumSlidingTick = psMeasureStat->dwCurTick;

    psMeasureStat->byCurSumSlidingNum = 0;// 经过的滑差次数,用来计算总的最大需量
	psMeasureStat->sSumSliding.dwSlidingCnt[0][0] = g_sEneryCnt.dwEPap + g_sEneryCnt.dwEPbp +g_sEneryCnt.dwEPcp;
	psMeasureStat->sSumSliding.dwSlidingCnt[1][0] = g_sEneryCnt.dwEPan + g_sEneryCnt.dwEPbn +g_sEneryCnt.dwEPcn;
	psMeasureStat->sSumSliding.dwSlidingCnt[2][0] = g_sEneryCnt.dwEQ1 + g_sEneryCnt.dwEQ4;//g_sEneryCnt.dwEQap + g_sEneryCnt.dwEQbp +g_sEneryCnt.dwEQcp;
	psMeasureStat->sSumSliding.dwSlidingCnt[3][0] = g_sEneryCnt.dwEQ2 + g_sEneryCnt.dwEQ3;//+g_sEneryCnt.dwEQcn;
	psMeasureStat->sSumSliding.dwSlidingCnt[4][0] = g_sEneryCnt.dwEQ1;
	psMeasureStat->sSumSliding.dwSlidingCnt[5][0] = g_sEneryCnt.dwEQ2;
	psMeasureStat->sSumSliding.dwSlidingCnt[6][0] = g_sEneryCnt.dwEQ3;
	psMeasureStat->sSumSliding.dwSlidingCnt[7][0] = g_sEneryCnt.dwEQ4;
    psMeasureStat->sSumSliding.byCurCntStartIndex = 0;
	psMeasureStat->sSumSliding.byCurCntEndIndex = 1;
	
    psMeasureStat->byCurRatioSlidingNum = 0;//
    psMeasureStat->sRatioSliding.dwSlidingCnt[0][0] = g_sEneryCnt.dwEPap + g_sEneryCnt.dwEPbp +g_sEneryCnt.dwEPcp;
	psMeasureStat->sRatioSliding.dwSlidingCnt[1][0] = g_sEneryCnt.dwEPan + g_sEneryCnt.dwEPbn +g_sEneryCnt.dwEPcn;
	psMeasureStat->sRatioSliding.dwSlidingCnt[2][0] = g_sEneryCnt.dwEQ1 + g_sEneryCnt.dwEQ4;
	psMeasureStat->sRatioSliding.dwSlidingCnt[3][0] = g_sEneryCnt.dwEQ2 + g_sEneryCnt.dwEQ3;
	psMeasureStat->sRatioSliding.dwSlidingCnt[4][0] = g_sEneryCnt.dwEQ1;
	psMeasureStat->sRatioSliding.dwSlidingCnt[5][0] = g_sEneryCnt.dwEQ2;
	psMeasureStat->sRatioSliding.dwSlidingCnt[6][0] = g_sEneryCnt.dwEQ3;
	psMeasureStat->sRatioSliding.dwSlidingCnt[7][0] = g_sEneryCnt.dwEQ4;
    psMeasureStat->sRatioSliding.byCurCntStartIndex = 0;

⌨️ 快捷键说明

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