📄 energy_module.c
字号:
//if Active power is positive,VAR is accumulated as it is;
//if Active power is negative,the sign of the VAR is reversed for the accumulation.
//This accumulation mode affects both the VAR registers and the VARCF output.
#define SAVARM 0x04
//1-Enables positive only accumulation of Active power in energy register and pulse output
#define POAM 0x02
//1-Enables absolute value accumulation of Active power in energy register and pulse output
#define ABSAM 0x01
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
#define IF_CF2 0x80 //Logic one indicates that a pulse of CF2 has been issued.
#define IF_CF1 0x40 //Logic one indicates that a pulse of CF1 has been issued.
#define IF_CYCEND 0x04 //Indicates the end of the energy accumulation over an integer number
#define IE_CF2 0x80 //1-a CF2 pulse issued creates a pending ADE interrupt
#define IE_CF1 0x40 //1-a CF1 pulse issued creates a pending ADE interrupt
#define IE_CYCEND 0x04 //1-the CYCEND flag set creates a pending ADE interrupt
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
/*
一、 初始参数设计依据:
1、 ADE7169芯片能量计量的固有数据:电压、电流通道最大输入值:0.5V ,在满刻度输入时最高输出频率为 CFmax=21.1KHz
2、 设计要求:标称电压(220V)设计为满刻度的60%左右,标称电流(Ib)设计为满刻度的15%以内。最大可作6~7倍表计。
3、 参数选择:
a)、电压采样的电阻分压比取1000:1,则电压满刻度百分比:V%FullScale=(220*1.414*1/1000)/0.5=62.23%
b)、电流采样的分流器300微欧,电流通道增益(IGain)设计为16倍,标称电流设计为10(40)A,则电流满刻度百分比:I%FullScale=(Ib*1.414*(300/1000000)*16)/0.5=13.576%
C)、标称电流10(40)A,脉冲常数取1600imp/KWh。
4、 标称电流Ib=10A 时,脉冲输出频率 CFib=(220*10*1600/1000)/3600= 0.9778Hz
5、 高频脉冲常数计算:CFden=(CFmax * V%FullScale * I%FullScale)/CFib = (21100*62.23% * 13.576%)/0.9778 = 1823 = 0x071E
二、校表
1、误差校正:(有功、无功、视在功率精度校准)
a)、原来误差增益寄存器清零
b)、校表台加标称Ib电流
c)、读得校表台的误差error
d)、计算误差增益寄存器值并写入之。公式:{(1/(1+%error)-1)* 2^12} 。
2、相位校正(在误差校正的基础上完成)
a)、原来相位校正寄存器置0x40
b)、校表台加相位差60度(感性0.5)标称Ib电流
c)、读得校表台的误差error
d)、计算相位校正偏移量并写入寄存器。公式:{(asin(%error) /(2*pi*F*1.22*10^(-6)))+ 0x40}。 pi=3.141592,F=50Hz
3、小信号偏移补偿 (在误差校正的基础上完成)
a)、原来偏移补偿寄存器清零
b)、校表台加相位差0度标称Ib1%电流
c)、读得校表台的误差error
d)、计算偏移补偿量并写入寄存器。公式:{%error * CF计算*(CF高频常数/(1+WGain/2^12))*(1/819.2KHz)*2^33}。
CF计算=在小电流和电压情况下算得的脉冲频率
CF高频常数=设置高频脉冲常数
WGain=完成校正时的误差增益寄存器值
*/
/*
__code const unsigned char EnergyStartUp[]= //第一次上电时能量计量模块初始化数据,数据长度:28byte。e2prom首地址:eCF1DEN
{ 0x01,0x04, 0x01,0x04,\
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,\
0x00,0x00, 0x00,0x00, 0x00,0x00, 0x00,0x00,\
0x40, 0x00 ,0x00, 0x00, 0x2B,0x05, 0x10,0x08};
*/
//==========================================================================================================================================================================
__idata struct{
unsigned char VGain; //电压转换常数
unsigned char IGain; //电流转换常数
};
__idata unsigned int Vrms; //电压有效值
__idata unsigned int Irms; //电流有效值
//---------------------------------------------------------------------------------------------------------------------------------
// 初始化计量模块
void EnergyModuleInit(void)
{
unsigned char loop,err,j,tempdata[4];
unsigned int i;
IEIP2_bit.EADE = 0; //关闭功率模块中断
loop=3;
while (loop--)
{ //Config the mode registers
err = WriteEnergyReg1(MODE1, (ENCF1OUT | ENCF2OUT)); // CF1,CF2引脚输出使能
err |= WriteEnergyReg1(MODE2, (ZXRMS|CF1_WATT|CF2_VAR|FREQSEL)); // 有效值由电压过零同步,CF1有功脉冲输出,CF2无功脉冲输出,输出线电压频率
err |= WriteEnergyReg1(WAVEMODE, (WAV1_Current|WAV2_Voltag|WAV_Clk)); // 电流电压曲线记录定义
err |= WriteEnergyReg1(NLMODE, (VANOLOAD_OFF|VANOLOAD_OFF|APNOLOAD_OFF)); // 电流、有功、无功、视在均不设置阀值
err |= WriteEnergyReg1(CALMODE, SEL_ICH_A); // 指定电流通道为:A通道
err |= WriteEnergyReg1(GAIN, (PGA2_X1|PGA1_X16)); // 电压通道增益x1,电流通道增益x16(用于分流器采样)
err |= WriteEnergyReg1(ACCMODE, (ABSVARM | ABSAM)); // 有功无功均选择绝对值累加
err |= WriteEnergyReg2(LINCYC, 0xB8,0x0B); // 取3000个周期累加能量作瞬时功率(即1分钟平均功率)
ClearWatchDog(); //喂狗
for (i=eIBGAIN,j=IBGAIN;i< eIBGAIN+16;) // 参数
{
err |= ReadE2prom_Api(i,(unsigned int)(&tempdata[0])+xRAM_Adr,2); //读E2PROM中的校表参数,地址1CH~23H
err |= WriteEnergyReg2(j,tempdata[0],tempdata[1]);
j++;
i+=2;
}
err |= ReadE2prom_Api(i,(unsigned int)(&tempdata[0])+xRAM_Adr,4); //读E2PROM中的校表参数 ,地址24H~26H ,10H
err |= WriteEnergyReg1(WDIV,tempdata[0]);
err |= WriteEnergyReg1(VARDIV,tempdata[1]);
err |= WriteEnergyReg1(VADIV,tempdata[2]);
err |= WriteEnergyReg1(PHCAL,tempdata[3]); //相位补偿
err |= ReadE2prom_Api(eCF1DEN,(unsigned int)(&tempdata[0])+xRAM_Adr,4); //读E2PROM中的校表参数 ,地址28H,2AH
err |= WriteEnergyReg2(CF1DEN,tempdata[0],tempdata[1]);
err |= WriteEnergyReg2(CF2DEN,tempdata[2],tempdata[3]); //高频脉冲常数
err |= ReadE2prom_Api(i,(unsigned int)(&VGain)+iRAM_Adr,2); //读E2PROM中的校表参数 ,电流电压增益
if (err == ErrorFalse)
break;
}
if (err == ErrorTrue)
{
Energy_ERR =1;
}
MIRQSTH = 0; //清状态标志
MIRQSTM = 0;
MIRQSTL = 0;
MIRQENL = 0;
MIRQENM = IE_CF2|IE_CF1; //CF1,CF2产生中断
MIRQENH = IE_CYCEND; //一个功率计数周期到中断
IEIP2_bit.EADE = 1; //允许功率模块中断
}
//---------------------------------------------------------------------------------------------------------------------------------
// 计量中断处理程序 (累加脉冲)
#pragma vector = 0x4b
__interrupt void ADE_ISR(void)
{
if(MIRQSTM_bit.CF1)
{
//CF1(有功)脉冲计数 //todo: Count CF1 for Active Energy
MIRQSTM_bit.CF1 = 0;
CF1Count++;
}
if(MIRQSTM_bit.CF2)
{
//CF2(无功)脉冲计数 //todo: Count CF2 for Reactive Energy
MIRQSTM_bit.CF2=0;
CF2Count++;
// G_LED ^= 1;
}
if(MIRQSTH_bit.CYCEND)
{
// 功率计算周期到
MIRQSTH_bit.CYCEND=0; //todo: Set Linecyc End Flag
PowerMeasure =1;
// G_LED ^= 1;
}
}
//---------------------------------------------------------------------------------------------------------------------------------
void EnergyADD( unsigned long __idata * Data)
{
*Data = BCD32Inc(*Data); //总电量+0.01kwh
if ((DQ_Fl>MAX_Fn)| (!DQ_Fl))
{
*(Data+3) = BCD32Inc(*(Data+3)); //费率电量+0.01kwh ,费率不正确,费率电量累加到平电量中
}
else
{
*(Data+DQ_Fl) = BCD32Inc(*(Data+DQ_Fl)); //费率电量+0.01kwh
}
}
//---------------------------------------------------------------------------------------------------------------------------------
void EnergyModule(void)
{
if (MIRQSTH_bit.RESET)
{
MIRQSTH_bit.RESET=0;
EnergyModuleInit(); //能量模块已复位,初始化模块
}
else
{
if (CF1Count > CF_const)
{ // 三相表时可以考虑正反向计量
IE_bit.EA = 0;
CF1Count -= CF_const;
EnergyADD(rPKwhPwr_Dtr); // rPKwhPwr_Dtr[0]=BCD32Inc(rPKwhPwr_Dtr[0]); //有功总电量、费率电量+0.01kwh
IE_bit.EA =1;
}
if (CF2Count > CF_const)
{ // 三相表时可以考虑正反向、四象限计量
IE_bit.EA = 0;
CF2Count -= CF_const;
EnergyADD(rPKvarhPwr_Dtr); //rPKvarhPwr_Dtr[0]=BCD32Inc(rPKvarhPwr_Dtr[0]); // EnergyADD(rPKvarhPwr_Dtr); //无功总电量、费率电量+0.01kvarh
IE_bit.EA =1;
}
if (PowerMeasure) //有功、无功功率处理
{
PowerMeasure=0;
//此处添加有功、无功功率处理。
}
TempChar[3]=0;
GetEnergySFR(VRMS,Temp8L,Temp8M,Temp8H); //读电压有效值
Vrms = (unsigned int)((Temp32*(124+VGain))>>16); //含一位小数(Vconst扩大10倍)124
Vrms = Hex16BCD(Vrms); //bin转换成BCD码
TempChar[3]=0;
GetEnergySFR(IRMS,Temp8L,Temp8M,Temp8H); //读电流有效值
Irms = (unsigned int)((Temp32*(124+IGain))>>16); //含二位小数(Iconst扩大100倍)
Irms = Hex16BCD(Irms); //bin转换成BCD码
if (PowerMeasure)
{
PowerMeasure =0;
//此处添加平均功率处理
}
}
}
//======================================================================================================
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -