📄 measure.c
字号:
/**************************************************************
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 + -