📄 calculate2.c
字号:
/*******************************电量的计算与管理********************************/
/*****由定时器4形成间隔为20ms的中断,在中断中指定数组,在主程序中计算***********/
#include <sfr16_lb.h>
#include <math.h>
#include <ExternDef.h>
#define _CALCULATE_DATA_
#include <variable.h>
#include <GMUDef.h>
#include <adf.h>
bit symbol_diandu1;//有功电度净值的正负:正为0负为1
bit symbol_diandu2;//无功电度净值的正负:正为0负为1
bit permit_diandu_flag;
unsigned int permit_diandu_num;
//变量定义
bit bIntPer20ms; //程序开始,闭锁周期计算一段时间,以保证采样数据稳定后再开始计算,此标志置1时才允许计算
bit bInt20ms; //发生20ms中断的标志.在20ms中断中计算电流与电压矢量,供显示主程序计算用.
xdata unsigned char SmpCount; //采样中断的采样点号,在0-240之间。采样队列也有240大小。
xdata unsigned char OldSmpPtr; //在周期采样处理中需要用到的采样数组的起始计算点号。
//计算中使用的新变量列表
xdata float fCalValWh0,fCalValWh1; //计算正、反向有功电度的累积计算结果
xdata float fCalValvar0,fCalValvar1; //计算正、反向有功电度的累积计算结果
xdata float fCalValVA; //计算视在电度的累积计算结果
xdata float VectorR[12]; //实时记录每通道电压电流的矢量:实部;按顺序依次是:Ua,Ia,Ub,Ib,Uc,Ic
xdata float VectorX[12]; //实时记录每通道电压电流的矢量:虚部;按顺序依次是:Ua,Ia,Ub,Ib,Uc,Ic
xdata float fCalP[4],fCalQ[4],fCalS[4]; //记录各个通道的计算功率:浮点数类型
//以下变量在DFT中使用的中间变量,部分完成参数传递。在其他地方禁止使用,
//此部分参数应采用其内部RAM数据,以提高程序的处理速度。
idata union {
long dlong;
int dint[2];
char dchr[4];
} DFTTmpData;
idata int DFTTmp1,DFTTmp2;
idata int DFTTmpR1,DFTTmpR2;
idata int DFTTmpX1,DFTTmpX2;
//int TmpR0,TmpX0;
idata int * DFTDataAddr; /*DFT变换中有效数据的地址指针*/
extern xdata unsigned int lcd_num;
extern xdata unsigned char RamFlag;
extern bit ram_select_flag;
//函数原型说明
void calculate(void);
void AlertHandle(void);
void NVRAM_write_byte (unsigned char data_out, unsigned int address); //写NVRAM
unsigned char NVRAM_read_byte (unsigned int address); //读NVRAM
//继电器操作函数
void Relay_Action(unsigned char n);
void Relay_UnAction(unsigned char n);
//以下为初始化存储的变量,仅作为测试用,以后删除
/*24点采样的快速傅立叶变换:输入为准备进行DFT变换的通道数据的首地址。存放在DFTDataAddr指针开始的连续24个数据中。
输出是变化后的复数结果,存放在变量DFTTmp1(实部)和DFTTmp2(虚部)中。 */
/*在通道处理时已经保证:每次进行傅氏变换,数据不会越出每一个采样的数据段,因此,在本函数的处理中不考虑采样数据越界的情况,以提高数据处理的速度 */
/*在WAVE环境下仿真12MHz标准51芯片,程序的执行时间是:1851us*/
/*使用的变量列表:
union {long dlong;int dint[2]; char dchr[4];} DFTTmpData; 数据转换用
int DFTTmp1,DFTTmp2; 同系数采样点合并用
int DFTTmpR1,DFTTmpR2; 第一、二组参数的实数部分
int DFTTmpX1,DFTTmpX2; 第一、二组参数的虚数部分
int xdata * data DFTDataAddr; DFT变换中有效数据的地址指针 */
void Fast_DFT(void)
{
/*以下是用于傅立叶分解用的系数组,在程序中将他们已经分解处理。
ConvCos[]={1024,989,886,724,512,265,0,-266,-512,-725,-887,-990,-1024,-990,-887,-725,-513,-266,-1,265,511,724,886,989};
ConvSin[]={0,265,511,724,886,989,1024,989,886,724,512,265,0,-266,-512,-725,-887,-990,-1024,-990,-887,-725,-513,-266};
由于按照DFT变换,有以下计算:
Rx =989*{f(1)-f(11)-f(13)+f(23)}+866*{f(2)-f(10)-f(14)+f(22)}+724*{f(3)-f(9)-f(15)+f(21)}+512*{f(4)-f(8)-f(16)+f(20)}+265*{f(5)-f(7)-f(17)+f(19)}+1024*{f(0)-f(12)};
Img=265*{f(1)+f(11)-f(13)-f(23)}+512*{f(2)+f(10)-f(14)-f(22)}+724*{f(3)+f(9)-f(15)-f(21)}+886*{f(4)+f(8)-f(16)-f(20)}+989*{f(5)+f(7)-f(17)-f(19)}+1024*{f(6)-f(18)};
设:Tmp00 = f(0)-f(12) ;
Tmp01 = f(1)-f(13) ; Tmp02 = f(11)-f(23);
Tmp11 = f(2)-f(14) ; Tmp12 = f(10)-f(22);
Tmp21 = f(3)-f(15) ; Tmp22 = f( 9)-f(21);
Tmp31 = f(4)-f(16) ; Tmp32 = f( 8)-f(20);
Tmp41 = f(5)-f(17) ; Tmp42 = f( 7)-f(19);
Tmp51 = f(6)-f(18);
Rx =989*(Tmp01-Tmp02)+886*(Tmp11-Tmp12)+724*(Tmp21-Tmp22)+512*(Tmp31-Tmp32)+265*(Tmp41-Tmp42)+1024*Tmp00;
Img=265*(Tmp01+Tmp02)+512*(Tmp11+Tmp12)+724*(Tmp21+Tmp22)+886*(Tmp31+Tmp32)+989*(Tmp41+Tmp42)+1024*Tmp51; */
/*== Rx:989*{f(1)-f(11)-f(13)+f(23)}; Img:{f(1)+f(11)-f(13)-f(23)} ====================================*/
DFTTmp1=*(DFTDataAddr+ 1)-*(DFTDataAddr+13);
DFTTmp2=*(DFTDataAddr+11)-*(DFTDataAddr+23);
DFTTmpData.dlong=990*((long)(DFTTmp1-DFTTmp2));
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpR1 = DFTTmpData.dint[1]>>1;
DFTTmpData.dlong=266*((long)(DFTTmp1+DFTTmp2));
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpX1 = DFTTmpData.dint[1]>>1;
/*== Rx: 724*{f(3)-f(9)-f(15)+f(21)}; Img:724*{f(3)+f(9)-f(15)-f(21)} ====================================*/
DFTTmp1=*(DFTDataAddr+ 3)-*(DFTDataAddr+15);
DFTTmp2=*(DFTDataAddr+ 9)-*(DFTDataAddr+21);
DFTTmpData.dlong=725*(long)(DFTTmp1-DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpR1 += DFTTmpData.dint[1]>>1;
DFTTmpData.dlong=725*(long)(DFTTmp1+DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpX1 += DFTTmpData.dint[1]>>1;
/*== Rx :265*{f(5)-f(7)-f(17)+f(19)}; Img:989*{f(5)+f(7)-f(17)-f(19)}; ====================================*/
DFTTmp1=*(DFTDataAddr+ 5)-*(DFTDataAddr+17);
DFTTmp2=*(DFTDataAddr+ 7)-*(DFTDataAddr+19);
DFTTmpData.dlong=266*(long)(DFTTmp1-DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpR1 += DFTTmpData.dint[1]>>1;
DFTTmpData.dlong=990*(long)(DFTTmp1+DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpX1 += DFTTmpData.dint[1]>>1;
/*== Rx :886*{f(2)-f(10)-f(14)+f(22)}; Img:512*{f(2)+f(10)-f(14)-f(22)}; ====================================*/
DFTTmp1=*(DFTDataAddr+ 2)-*(DFTDataAddr+14);
DFTTmp2=*(DFTDataAddr+10)-*(DFTDataAddr+22);
DFTTmpData.dlong=886*(long)(DFTTmp1-DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpR2 = DFTTmpData.dint[1]>>1;
DFTTmpX2=DFTTmp1+DFTTmp2;
/*DFTTmpData.dlong=512*(long)DFTTmpX2;DFTTmpData.dchr[3]=DFTTmpData.dchr[2];DFTTmpData.dchr[2]=DFTTmpData.dchr[1];DFTTmpX2 = DFTTmpData.dint[1]/2; */
/*== Rx :512*{f(4)-f(8)-f(16)+f(20)}; Img:886*{f(4)+f(8)-f(16)-f(20)}; ====================================*/
DFTTmp1=*(DFTDataAddr+ 4)-*(DFTDataAddr+16);
DFTTmp2=*(DFTDataAddr+ 8)-*(DFTDataAddr+20);
/*DFTTmpData.dlong=512*(long)DFTTmpR4;DFTTmpData.dchr[3]=DFTTmpData.dchr[2];DFTTmpData.dchr[2]=DFTTmpData.dchr[1];DFTTmpR2 += DFTTmpData.dint[1]/2; */
DFTTmpR2 += (DFTTmp1-DFTTmp2);
DFTTmpData.dlong=886*(long)(DFTTmp1+DFTTmp2);
DFTTmpData.dchr[3]=DFTTmpData.dchr[2];
DFTTmpData.dchr[2]=DFTTmpData.dchr[1];
DFTTmpX2 += DFTTmpData.dint[1]>>1;
/*== Rx :1024*{f(0)-f(12)}; Img:1024*{f(6)-f(18)}; =======================================================*/
DFTTmp2=*DFTDataAddr-*(DFTDataAddr+12);
/*DFTTmpData.dlong=1024*(long)DFTTmp2; DFTTmpData.dchr[3]=DFTTmpData.dchr[2]; DFTTmpData.dchr[2]=DFTTmpData.dchr[1]; DFTTmpR2 += DFTTmpData.dint[1]/2; */
DFTTmp2 +=DFTTmp2;
DFTTmpR2 += DFTTmp2;
DFTTmp1=*(DFTDataAddr+ 6)-*(DFTDataAddr+18);
/*DFTTmpData.dlong=1024*(long)DFTTmp1;DFTTmpData.dchr[3]=DFTTmpData.dchr[2];DFTTmpData.dchr[2]=DFTTmpData.dchr[1];DFTTmpX2 += DFTTmpData.dint[1]/2; */
DFTTmp1 += DFTTmp1;
DFTTmpX2 += DFTTmp1;
DFTTmp1 = (DFTTmpR1>>1) + (DFTTmpR2>>1);
DFTTmp2 = (DFTTmpX1>>1) + (DFTTmpX2>>1);
}
void IntPer20ms(void) //每20毫秒响应的一次中断,作为周期量计算的定时器
{
xdata float fTmpR1,fTmpX1,fTmpR2,fTmpX2;
xdata float fValR1,fValX1;
if(bIntPer20ms==FALSE) return;
//在程序刚开始时需要闭锁一段时间,使采样数据满足至少一个周期的有效队列后,本程序才开始计算
//一旦在突变量检测中发现监控对象出现故障,本程序也终止计算。
//此变量在程序初始化时清零,在每周期采样中满足要求时置位。
if(bInt20ms==TRUE){
bInt20ms=FALSE;
//以下完成A相电压、电流的DFT分解,在两表法时接Uab,Ia;在三表法时接Ua,Ia
DFTDataAddr=Chan_Ua;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
fValR1 = fSetK[0] * fTmpR2 ; //完成其幅值与相位的校正:实部,A相电压是参考相没有角度的校正
fValX1 = fSetK[0] * fTmpX2 ; //完成其幅值与相位的校正:虚部,A相电压是参考相没有角度的校正
VectorR[0] = fValR1;
VectorX[0] = fValX1;
DFTDataAddr=Chan_Ia;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
//,A相电流及后续电量需要进行角度的校正
fTmpR1 = fSetK[1] * ( fTmpR2 * fSetArjR[1] - fTmpX2 * fSetArjX[1] ); //完成其幅值与相位的校正:实部
fTmpX1 = fSetK[1] * ( fTmpX2 * fSetArjR[1] + fTmpR2 * fSetArjX[1] ); //完成其幅值与相位的校正:虚部
VectorR[1] = fTmpR1;
VectorX[1] = fTmpX1;
//A相有功功率和无功功率的计算
fCalP[0]= (fValR1 * fTmpR1 + fValX1 * fTmpX1);
fCalQ[0]= (fValX1 * fTmpR1 - fValR1 * fTmpX1); //记录各个通道的计算功率:浮点数类型
//以下完成C相电压、电流的DFT分解,在两表法时接Ucb,Ic;在三表法时接Uc,Ic
DFTDataAddr=Chan_Uc;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
//,C相电压通道的角度与幅值校正
fValR1 = fSetK[4] * ( fTmpR2 * fSetArjR[4] - fTmpX2 * fSetArjX[4] ); //完成其幅值与相位的校正:实部
fValX1 = fSetK[4] * ( fTmpX2 * fSetArjR[4] + fTmpR2 * fSetArjX[4] ); //完成其幅值与相位的校正:虚部
VectorR[4] = fValR1;
VectorX[4] = fValX1;
DFTDataAddr=Chan_Ic;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
//,C相电流角度的校正
fTmpR1 = fSetK[5] * ( fTmpR2 * fSetArjR[5] - fTmpX2 * fSetArjX[5] ); //完成其幅值与相位的校正:实部
fTmpX1 = fSetK[5] * ( fTmpX2 * fSetArjR[5] + fTmpR2 * fSetArjX[5] ); //完成其幅值与相位的校正:虚部
VectorR[5] = fTmpR1;
VectorX[5] = fTmpX1;
//C相有功功率和无功功率的计算
fCalP[2]= (fValR1 * fTmpR1 + fValX1 * fTmpX1) ;
fCalQ[2]= (fValX1 * fTmpR1 - fValR1 * fTmpX1) ; //记录各个通道的计算功率:浮点数类型
if(bMeter3!=0){ //装置采用三表法接线,此处需要计算Ub,Ib的大小.
//以下完成B相电压、电流的DFT分解,在两表法时不接c;在三表法时接Ub,Ib
DFTDataAddr=Chan_Ub;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
//,B相电压通道的角度与幅值校正
fValR1 = fSetK[2] * ( fTmpR2 * fSetArjR[2] - fTmpX2 * fSetArjX[2] ); //完成其幅值与相位的校正:实部
fValX1 = fSetK[2] * ( fTmpX2 * fSetArjR[2] + fTmpR2 * fSetArjX[2] ); //完成其幅值与相位的校正:虚部
VectorR[2] = fValR1;
VectorX[2] = fValX1;
DFTDataAddr=Chan_Ib;
DFTDataAddr=DFTDataAddr+ OldSmpPtr;
Fast_DFT();
fTmpR2=(float)DFTTmp2;
fTmpX2=(float)DFTTmp1;//刘兵加
//B相电流及后续电量需要进行角度的校正
fTmpR1 = fSetK[3] * ( fTmpR2 * fSetArjR[3] - fTmpX2 * fSetArjX[3] ); //完成其幅值与相位的校正:实部
fTmpX1 = fSetK[3] * ( fTmpX2 * fSetArjR[3] + fTmpR2 * fSetArjX[3] ); //完成其幅值与相位的校正:虚部
VectorR[3] = fTmpR1;
VectorX[3] = fTmpX1;
fCalP[1]= (fValR1 * fTmpR1 + fValX1 * fTmpX1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -