AD采样实现AC计量之算法实现与流程

网上的资料还是很少的,把半个月的成果给大家分享吧,先上代码,以后有空对其分析。


measure.c

 /****************************************************************************
 *$Author:   ZhengFang     $
 *$Date:     October, 2013 $
 ****************************************************************************/

#include "DSP28x_Project.h"
#include "global.h"

#define SAMPLE_F       8000.0f
#define N              1024
#define WAVE_F         50.0f
#define PI             3.14159265f

#define ZERO_CNT_CYC   100
#define FFTforFreqEn   1


#define IIRLpfB0_U     0.0061f
#define IIRLpfA1_U     (-1.7672f)
#define IIRLpfA2_U     0.7916f



#define	RFFT_STAGES	10
#define	RFFT_SIZE	(1 << RFFT_STAGES) 

#pragma DATA_SECTION(RFFTin1Buff,"EXRAMDATA");  //Buffer alignment for the input array,
float32 RFFTin1Buff[RFFT_SIZE];                 //RFFT_f32u(optional), RFFT_f32(required)
                                                //Output of FFT overwrites input if 
                                                //RFFT_STAGES is ODD
#pragma DATA_SECTION(RFFToutBuff,"EXRAMDATA"); 
float32 RFFToutBuff[RFFT_SIZE];                 //Output of FFT here if RFFT_STAGES is EVEN

#pragma DATA_SECTION(RFFTmagBuff,"EXRAMDATA");
float32 RFFTmagBuff[RFFT_SIZE/2+1];             //Additional Buffer used in Magnitude calc
 
#pragma DATA_SECTION(RFFTF32Coef,"EXRAMDATA");
float32 RFFTF32Coef[RFFT_SIZE];                 //Twiddle buffer

RFFT_F32_STRUCT rfft;



//_RealTimeData RealTimeData;

_CalcCeof CalcCeof;

float32 ElcPowerFreq;

//Uint16 PowerFreqPre = 50000;
//Uint16 PowerFreq = 50000;
#define CALC_POWER          0x0001
#define CALC_FREQUENC       0x0002
#define CALC_HARMONIC       0x0004
#define CALC_URMS           0x0008


_ChannelData ChannelData[CHN_NUM];

//float32 VoltSmpBuf[60] = {0};
//int16 pVolt = 59;
//float32 InstanVolt = 0;
//float32 InstanCurr = 0;
//float32 ShiftPhsVolt = 0;

int16 WaveTmp = 0;
//float32 Urms2Tmp = 0;
//int16 CalcLen = 160*3;
//int16 Urms2Num = 0;

Uint64 SamSum;
Uint64 ErrSum;


volatile int16 FFTProc = 0;
volatile int16 FFTSmpNum = 0;
//volatile int16 ZeroStart = ZERO_CNT_CYC+1;
//volatile int16 PeriodSyn = 0;
//int16 ZeroTimer = 0;
int16 QuasiWin = 160;

#pragma DATA_SECTION(ViewBuffer0,"EXRAMDATA");
int16 ViewBuffer0[2000];
int16 pView = 0;
#pragma DATA_SECTION(ViewBuffer1,"EXRAMDATA");
float32 ViewBuffer1[2000];

	
/*int32 IIrForU[3] = 
{
    0, 0, 0
};
int16 IIrForUout[2] = 
{
    0, 0
};*/

//int16 PhaseInt = 0;
//float32 PhaseFloat = 0.0;
//float32 PhaseFloat2 = 0.0;

#define IIRLpfB0 11        //b0=b2 Q15
#define IIRLpfA1 (-15954)  //Q13
#define IIRLpfA2 7773      //Q13	

//float32 IIrForP[3];
//float32 IIrForQ[3];

//float32 AcPowTmp = 0;
//float32 RePowTmp = 0;


//float32 actpower = 0;
//float32 reactpower = 0;

//const int Quadrant[4] = {1,2,4,3};
const int Quadrant[4] = {0, 90, 270, 180};

void CalcCeofFun(void)
{
    ESTOP0;
    CalcCeof.k = (CalcCeof.u2-CalcCeof.u1)/(CalcCeof.ad2-CalcCeof.ad1);
    CalcCeof.b = CalcCeof.u2 - CalcCeof.ad2*CalcCeof.k;
    ESTOP0;
}
float32 Fre2Queue(Uint16 val)
{
    static Uint16 pAddr = 0;
    float32 FunFreTmp[4] = {50.0, 50.0, 50.0, 50.0};
    float32 res;
    pAddr &= 3;
    FunFreTmp[pAddr] = val;
    pAddr++;
    res = (FunFreTmp[0] + FunFreTmp[1] + FunFreTmp[2] + FunFreTmp[3]) / 4;
    return res;
}
void MakeWave(void)  
{
    int16 i;
    float32 RadStep; //  2*pi*WAVE_F/SAMPLE_F
    float32 Rad;
    float32 Fre = 50.0;
    Rad = 0.0f;
    //ESTOP0;
    RadStep = 2.0*PI*Fre / (SAMPLE_F/2);
	for(i = 0; i < RFFT_SIZE; i++)
	{
		//RFFTin1Buff[i]   = sin(Rad) + cos(Rad*2.3567); //Real input signal
		RFFTin1Buff[i]   = 311*sin(Rad) + 30*sin(3*Rad)+ 50*sin(5*Rad)+ 70*sin(20*Rad);
		//FFTImag_in[i] = cos(Rad*8.345) + sin(Rad*5.789);		
		Rad = Rad + RadStep;
	}
}

void SysFFTCalc(void)
{
    int16 i;
    for (i=0; i < RFFT_SIZE; i++)
    {
      	RFFToutBuff[i] = 0;			   //Clean up output buffer
    }

    for (i=0; i < RFFT_SIZE/2; i++) 
    {
     	RFFTmagBuff[i] = 0;		       //Clean up magnitude buffer
    }
    RFFT_f32u(&rfft);				   //Calculate real FFT
    RFFT_f32_mag(&rfft);				//Calculate magnitude
}
void SysFFTInit(void)
{
    int16 i;
    rfft.FFTSize   = RFFT_SIZE;
    rfft.FFTStages = RFFT_STAGES;   
    rfft.InBuf     = &RFFTin1Buff[0];  //Input buffer
    rfft.OutBuf    = &RFFToutBuff[0];  //Output buffer
    rfft.CosSinBuf = &RFFTF32Coef[0];  //Twiddle factor buffer
    rfft.MagBuf    = &RFFTmagBuff[0];  //Magnitude buffer

    RFFT_f32_sincostable(&rfft);       //Calculate twiddle factor
 
    for(i = 0; i < RFFT_SIZE; i++)
    {
      	RFFToutBuff[i] = 0;			   //Clean up output buffer
    }

    for(i = 0; i < RFFT_SIZE/2; i++) 
    {
     	RFFTmagBuff[i] = 0;		       //Clean up magnitude buffer
    }
}
float32 VoltRmsCalc(float32 *fdata, int16 n)
{
    int i;
    float32 *p = fdata;
    float32 tmp;
    float32 sum = 0;
    for(i = 0; i < n; i++)
    {
        tmp = *p;
        
        sum += tmp * tmp;

    }
    sum/=n;
    sum = __ffsqrtf(sum);
    return sum;
}
#define AD_K  0.06020924f
#define AD_B  (-6.361816f)
void AD2RealVal(int16 * psrc, float32 * pdst)
{
    *pdst = (*psrc) * AD_K + AD_B;
}
void cal_test(void)
{
    volatile float res;
    float32 s[5]={1.11,2.22,3.33,4.44,5.55};
    int t[5] = {1,2,3,4,5};
    res = s[0] * t[0];
    res = s[1] * s[2];
    res = VoltRmsCalc(s, 2);
    res = __ffsqrtf(3.0f); 
    res = sin(PI/4.0f);
}

void HarmonicAnalysis(_ChannelData *pd)
{
    int16 m, n, k, i;
    int16 pitch_i = 0;	 
    //int16 k = 0;
    float32 AmpliTemp = 0.0;
    float32 deltaK = 0.0;
    float32 deltaK2 = 0.0;
    float32 maxValue = 0.0;
    float32 maxValue2 = 0.0;
    float32 fretmp;

    
    for(m = 0; m < 23; m++)
    {
        pd->RealTimeData.HarmAmp[m] = 0.0;
        pd->RealTimeData.HarmFre[m] = 0.0;
    }
    for(m = 0; m < (RFFT_SIZE/2); m++)
    {
        if(RFFTmagBuff[m] > maxValue)
        {
            maxValue = RFFTmagBuff[m];
            pitch_i = m;
        }
    }
    pd->RealTimeData.HarmAmp[0] = 2 * RFFTmagBuff[0] / (RFFT_SIZE); //DC amp = A/N
    if(pitch_i == 0)
    {
        pd->RealTimeData.HarmFre[1] = 0.0;
    }
    else
    {
        if((RFFTmagBuff[pitch_i - 1] == 0) && (RFFTmagBuff[pitch_i + 1] == 0))
        {
            deltaK = 0.0;
        }
        else if(RFFTmagBuff[pitch_i - 1] <= RFFTmagBuff[pitch_i + 1])
        {
        //between HanMaxK and HanMaxK+1
        //deltaK=[2Y(K+1)-Y(K)]/[Y(K+1)+Y(K)]
            deltaK = (float32)(2 *RFFTmagBuff[pitch_i + 1] - RFFTmagBuff[pitch_i]) / (float32)(RFFTmagBuff[pitch_i + 1] + RFFTmagBuff[pitch_i]);
        }
        else
        {
            //deltaK=[Y(K)-2Y(K-1)]/[Y(K)+Y(K-1)]
            deltaK = (float32)(RFFTmagBuff[pitch_i] - 2 * RFFTmagBuff[pitch_i - 1]) / (float32)(RFFTmagBuff[pitch_i] + RFFTmagBuff[pitch_i - 1]);
        }
    } 

    //RealTimeData.HarmFre = ((pitch_i + deltaK)*(float)SAMPLE_F / (2 * RFFT_SIZE));
    pd->RealTimeData.HarmFre[1] = (pitch_i + deltaK)*3.9058f;
    if (deltaK <= 0)
    //delta linit +-0 and +-1
    {
        deltaK2 = 1 + deltaK; //deltaK2 > 0
        if(deltaK > (- 1e-4))
        {
        //deltaK limit -0
        //sinx=x x limit 0 , here use 1e-4
            AmpliTemp = 2 * maxValue;
        }
        else if (deltaK2 < 1e-4)
        {
        //deltaK limit -1
            AmpliTemp = 4 * maxValue;
        }
        else
        {
            AmpliTemp = 2 * PI * maxValue * deltaK / sin(PI *deltaK)*(1-deltaK * deltaK);
        }
         		
    }
    else//deltaK > 0
    {
        deltaK2 = 1-deltaK;
        if (deltaK < 1e-4)
        //deltaK limit +0
            AmpliTemp = 2 * maxValue;
        else if (deltaK2 < 1e-4)
        //deltaK limit +1
            AmpliTemp = 4 * maxValue;
        else
            AmpliTemp = 2 * PI * maxValue * deltaK / sin(PI *deltaK)*(1-deltaK * deltaK);
    }
    if(pd->RealTimeData.HarmFre[1] > 1e-3)
    {
        pd->RealTimeData.HarmAmp[1] = (1.4142 *AmpliTemp) / (RFFT_SIZE); //AC amp = 2*A/N
    }
    else
    {
        pd->RealTimeData.HarmAmp[1] = 0.0;
    }

    //j_step = 2*Frequence*RFFT_SIZE/SAMPLE_F;

    for (n = 2; n < 23; n++)
    {
        //pitch_i = pitch_i + 10;
        pitch_i = pitch_i + 10;
        //pitch_i = j_step*n-2;
        maxValue2 = RFFTmagBuff[pitch_i];
        if(pitch_i < (RFFT_SIZE / 2))
        {
            for(k = pitch_i; k < pitch_i + 4; k++)
            {
             
                if (RFFTmagBuff[k] > maxValue2)
                {
                    maxValue2 = RFFTmagBuff[k];
                    pitch_i = k;
                }
            }
            if((RFFTmagBuff[pitch_i - 1] == 0) && (RFFTmagBuff[pitch_i + 1] == 0))
            {
                deltaK = 0.0;
            }
            else if(RFFTmagBuff[pitch_i - 1] <= RFFTmagBuff[pitch_i + 1])
            {
                deltaK = (float)(2 *RFFTmagBuff[pitch_i + 1] - RFFTmagBuff[pitch_i]) / (float)(RFFTmagBuff[pitch_i + 1] + RFFTmagBuff[pitch_i]);
            }
            else
            {
                deltaK = (float)(RFFTmagBuff[pitch_i] - 2 * RFFTmagBuff[pitch_i - 1]) / (float)(RFFTmagBuff[pitch_i] + RFFTmagBuff[pitch_i - 1]);
            }
            
            if(deltaK <= 0)
            {
                deltaK2 = 1+deltaK;
                if (deltaK > (- 1e-4))
                {
                    AmpliTemp = 2 * maxValue2;
                }
                else if (deltaK2 < (1e-4))
                {
                    AmpliTemp = 4 * maxValue2;
                }
                else
                {
                    AmpliTemp = 2 * PI * maxValue2 * deltaK / sin(PI *deltaK)*(1-deltaK * deltaK);
                }
            }
            else
            {
                deltaK2 = 1-deltaK;
                if(deltaK < 1e-4)
                {
                    AmpliTemp = 2 * maxValue2;
                }
                else if(deltaK2 < 1e-4)
                {
                    AmpliTemp = 4 * maxValue2;
                }
                else
                {
                    AmpliTemp = 2 * PI * maxValue2 * deltaK / sin(PI *deltaK)*(1-deltaK * deltaK);
                }
            }
            fretmp = (pitch_i + deltaK)*3.9058f;
            if(pd->RealTimeData.HarmFre[1] < 40.0)
            {
                pd->RealTimeData.HarmAmp[n] = (1.4142 *AmpliTemp) / (RFFT_SIZE);
                if(pd->RealTimeData.HarmAmp[i] < 1e-1)
                {
                    pd->RealTimeData.HarmAmp[i] = 0.0;
                }
            }
            else
            {
                //fretmp += 0.5;
                i = (int16)(fretmp/pd->RealTimeData.HarmFre[1] + 0.5);
                if(i > 1 && i < 23)
                {
                    pd->RealTimeData.HarmAmp[i] = (1.4142 *AmpliTemp) / (RFFT_SIZE);
                    pd->RealTimeData.HarmFre[i] = fretmp;
                    if(pd->RealTimeData.HarmAmp[i] < 1e-1)
                    {
                        pd->RealTimeData.HarmAmp[i] = 0.0;
                        pd->RealTimeData.HarmFre[i] = 0.0;
                    }
                }
            }
        }
    }
    return ;
}
#if 0
RN(n)
Hamming 0.54-0.46*cos[2*PI*n/(N-1)]         0≤n≤N-1
Hanning 0.5*[1-cos[2*PI*n/(N-1)]]           0≤n≤N-1
Blackman 0.42-0.5*cos[2*PI*n/(N-1)]+0.08cos[4*PI*n/(N-1))*RN(n)
h(i)=sqrt(re(i)*re(i)+im(i)*im(i))
dBh(i)=20*log (h(i)) 
#endif
void HarmonicProcess(void)
{
    Uint16 i;
    
    _ChannelData *pd;

    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_HARMONIC) == 0)
            continue;
    
        for (i = 0; i < RFFT_SIZE; i++)
        {
            RFFTin1Buff[i] = (RFFTin1Buff[i] * HanningWin[i]) / 16384;

        }
        
        SysFFTCalc();
        HarmonicAnalysis(pd);

        #if FFTforFreqEn    
        if((pd->RealTimeData.HarmFre[1] > 45.0) && (pd->RealTimeData.HarmFre[1] < 55.0))
        {
            //SumFrequency = SumFrequency + RealTimeData.HarmFre;
        }
        else 
        {
            pd->RealTimeData.HarmFre[1] = 0;
        }
        #endif 
       
        //ESTOP0;
    	ElcPowerFreq = Fre2Queue(pd->RealTimeData.HarmFre[1]);
    }
}

void CalcFreq(void)
{
    static Uint16 j0 = 0, j1 = 0;
    int16 tempvar, i;
    _ChannelData *pd;
    

    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_FREQUENC) == 0)
            continue;
        if(pd->ZeroStart > 0)
        {
            if((pd->IIrForUout[0] >= 0) && (pd->IIrForUout[1] < 0))
            {
                if(pd->ZeroTimer == 0)
                {
                    pd->ZeroTimer = 1;
                    //ESTOP0;
                    //StartSample = 1;
                    pd->ZeroStart = ZERO_CNT_CYC+1;
                    //RealTimeData.Umax = 0;
                }
                pd->ZeroStart--;
                pd->PeriodSyn = 1;
            }
            if(pd->ZeroTimer)
            {
                pd->ZeroTimer++;
            }
        }
        else
        {
            //ESTOP0;
            if(i == 0)
            {
                j0++;
                if(j0%4 == 0)
                {
                    ESTOP0;
                }
            }
            else
            {
                j1++;
                if(j1%4 == 0)
                {
                    ESTOP0;
                }
            }
            if((pd->ZeroTimer > 14545) && (pd->ZeroTimer < 17777))
            {
                //PowerFreqPre = PowerFreq;
                //PowerFreq = 800000000 / (ZeroTimer-1);
                pd->RealTimeData.Frequency = 800000.0f/(pd->ZeroTimer);
                
                //ESTOP0;
                tempvar = 8000.0f / pd->RealTimeData.Frequency;
                tempvar = tempvar - QuasiWin;
                if ((tempvar > 3) || (tempvar <  - 3))
                {
                    QuasiWin = tempvar+QuasiWin;
                }
                
            }

            pd->ZeroStart = 1;
            pd->ZeroTimer = 0;
            //ZeroCounter = ZERO_CNT_CYC;
        }
    }
}
void Sample2Buff(void)
{
    static Uint16 div = 0;
    //static int16 LastTmp = 0, PreTmp = 0, flag = 1;
    static float32 Rad0 = 0, Rad1 = 0;
    float32 ftmp;
    int16 tmp, i;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        
        pd = &ChannelData[i];
        
        #if 0
        ReadCpldInt(ADC_S1_REG+i, &tmp);
        /*(ABS(tmp-(LastTmp+PreTmp)/2) > 200)
        {
            //ESTOP0;
            if(flag == 0)
            {
                tmp = 2*LastTmp - PreTmp;
            }
            else
            {
                if(flag > 2)
                {
                    PreTmp = LastTmp = tmp;
                }
            }
            flag++;
        }
        else
        {
            PreTmp = LastTmp;
            LastTmp = tmp;
            flag = 0;
        }*/
        #if 0
        ViewBuffer0[pView] = tmp;
        if(++pView > 1999)
        {
            pView = 0;
            ftmp = CalcAvgInt(&ViewBuffer0[500], 1000);
            //CalcCeofFun();
            ESTOP0;
            
        }
        #endif
        /*if(tmp > 8860 || tmp < -8860) //bye-bye-le ^_^ filter the inlegel val
        {
            tmp = LastTmp;   
        }
        else
        {
            LastTmp = tmp;
        }*/
        
        AD2RealVal(&tmp, &ftmp);
        /*SamSum++;
        if(tmp > 2500 || tmp < -2500)
        {
            //ESTOP0;
            ErrSum++;
        }
        if(ErrSum > 10)
        {
            //ESTOP0;
        }*/
        #if 0
        ViewBuffer1[pView] = ftmp;
        if(++pView > 1999)
        {
            pView = 0;
            res = CalcAvgFloat(&ViewBuffer1[500], 1000);
            //CalcCeofFun();
            ESTOP0;
            
        }
        #endif

        #else
        
        if(i == 0)
        {
            Rad0 += 0.03927;
            //Rad0 += 0.03832743;//48.8Hz
            if(Rad0 > 2*PI)
            {
                Rad0 -= 2*PI;
            }
            //ftmp = 311.08f*sin(Rad)+70.7*sin(4*Rad)+56.56*sin(5*Rad)+42.42*sin(13*Rad)+28.28*sin(20*Rad)+10;
            ftmp = 311.127f*sin(Rad0);
        }
        else
        {
            Rad1 += 0.03927;
            //Rad1 += 0.041469;//52.8Hz
            if(Rad1 > 2*PI)
            {
                Rad1 -= 2*PI;
            }
            //ftmp = 7.071f*sin(Rad1+1.0472) /*+ 7.07*sin(8*Rad)*/;//60*
            ftmp = 7.071f*sin(Rad1-3.927);
        }
        #endif
        
        pd->VoltSmpBuf[pd->pVolt] = ftmp;
        
        if(tmp > pd->RealTimeData.Umax)
        {
            pd->RealTimeData.Umax = tmp;
        }
        if(tmp < pd->RealTimeData.Umin)
        {
            pd->RealTimeData.Umin = tmp;
        }
        pd->pVolt--;
        if(pd->pVolt <= -1)
        {
            pd->pVolt = SMP_NUM-1;
        }
        //VoltSmpBuf[pVolt] = WaveTmp;

        //pd++;
        if((pd->CalcConfig & CALC_HARMONIC) == 0)
            continue;
        if((div & BIT0) && (!FFTProc))
        {
            RFFTin1Buff[FFTSmpNum++] = ftmp;
            if(FFTSmpNum >= RFFT_SIZE)
            {
                FFTProc = 1;
                FFTSmpNum = 0;
            }
        }
    }
    div++;
}
void PhaCalForAc(void)
{
    int16 p;
    int16 i;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];

        p = pd->pVolt + 4;
        if(p > SMP_NUM-1)
        {
            p -= SMP_NUM;
        }
        pd->InstanVolt = pd->VoltSmpBuf[p];

        //pd++;
    }
}
void PhaCalForRe(void)
{
    int16 p0, p1, p2;
    float32 res1, res2;

    int16 i;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_POWER) == 0)
            continue;
        
        p0 = pd->PhaseInt + pd->pVolt + 3;
        if (p0 > SMP_NUM-1)
            p0 = p0 - SMP_NUM;
        p1 = pd->PhaseInt + pd->pVolt + 4;
        if (p1 > SMP_NUM-1)
            p1 = p1 - SMP_NUM;
        p2 = pd->PhaseInt + pd->pVolt + 5;
        if (p2 > SMP_NUM-1)
            p2 = p2 - SMP_NUM;

        res1 = pd->PhaseFloat2 * (pd->VoltSmpBuf[p2] + pd->VoltSmpBuf[p0] - 2 * pd->VoltSmpBuf[p1]);
        res2 = pd->PhaseFloat * (pd->VoltSmpBuf[p2] - pd->VoltSmpBuf[p0]);
        pd->ShiftPhsVolt = (res1 + res2) / 2 + pd->VoltSmpBuf[p1];

        //pd++;
    }
}

/*
Fs=8000Hz
fp=120Hz
rp=0.05
fs=1500Hz
As=0.02
=>
b0=b2=0.0061
b1=0.0122 
a1=-1.7672
a2=0.7916
*/

void IIRLpfVolt(void)
{
    int16 U_in;

    int16 i;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_FREQUENC) == 0)
            continue;
        U_in = pd->InstanVolt;
      

        pd->IIrForUout[1] = pd->IIrForUout[0];
        pd->IIrForU[2] = pd->IIrForU[1];
        pd->IIrForU[1] = pd->IIrForU[0];

        pd->IIrForU[0] = U_in - ((IIRLpfA1_U)*(pd->IIrForU[1]) + IIRLpfA2_U * (pd->IIrForU[2]));
        pd->IIrForUout[0] = IIRLpfB0_U *(pd->IIrForU[0] + 2 * pd->IIrForU[1] + pd->IIrForU[2]);

        //pd++;
    }

}

void IIRLpfPower(void)
{
    //y(i)=b0*x(i)+b1*x(i-1)+b2*x(i-2)-a1*y(i-1)-a2*y(i-2)
    // =b0{x(i)+x(i-2)+2x(x-1)}-a1*y(i-1)-a2*y(i-2)		
    float ftmp;

    int16 i;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_POWER) == 0)
            continue;
        ftmp = pd->InstanVolt * pd->InstanCurr;

        pd->IIrForP[2] = pd->IIrForP[1];
        pd->IIrForP[1] = pd->IIrForP[0];
        pd->IIrForP[0] = ftmp - (IIRLpfA1 *pd->IIrForP[1] + IIRLpfA2 * pd->IIrForP[2]) / 8192; //w延迟器
        pd->AcPowerTmp = IIRLpfB0 *(pd->IIrForP[0] + 2 * pd->IIrForP[1] + pd->IIrForP[2]) / 32768;

        ftmp = pd->ShiftPhsVolt * pd->InstanCurr;

        pd->IIrForQ[2] = pd->IIrForQ[1];
        pd->IIrForQ[1] = pd->IIrForQ[0];
        pd->IIrForQ[0] = ftmp - (IIRLpfA1 *pd->IIrForQ[1] + IIRLpfA2 * pd->IIrForQ[2]) / 8192;
        pd->RePowerTmp = IIRLpfB0 *(pd->IIrForQ[0] + 2 * pd->IIrForQ[1] + pd->IIrForQ[2]) / 32768;

        //pd++;
    }
 
}

void QuasiFunc(void)
{
    float32 ftmp;
    //int32 tmp;
    int16 i;
    _ChannelData *pd;
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_URMS) == 0)
            continue;
        
        if(pd->PeriodSyn == 1)
        {
            //tmp = CurrVolt;
            pd->Urms2Sum += pd->InstanVolt * pd->InstanVolt;
            //ViewBuffer1[Urms2Num] = CurrVolt;
            //Urms2Tmp += tmp*tmp;
            pd->AcPowSum += pd->AcPowerTmp;
            pd->RePowSum += pd->RePowerTmp;
            pd->Urms2Num++;
            //VoltSmpBufTmp0[SampleNum] = CurrVolt;
            
            
            if(pd->Urms2Num == pd->CalcLen)
            {
                pd->UpdataFlg = 1;
                //if(i == 0)
                    //ESTOP0;
                #if 0
                ftmp = pd->Urms2Sum/(float32)(pd->Urms2Num);
                ftmp = __ffsqrtf(ftmp);
                pd->RealTimeData.Urms = ftmp;
                pd->RealTimeData.AcPower = pd->AcPowSum/pd->Urms2Num;
                pd->RealTimeData.RePower = pd->RePowSum/pd->Urms2Num;
                pd->RealTimeData.AcPower = ABS(pd->RealTimeData.AcPower);
                pd->RealTimeData.RePower = ABS(pd->RealTimeData.RePower);
                ftmp = pd->RealTimeData.AcPower * pd->RealTimeData.AcPower
                    + pd->RealTimeData.RePower * pd->RealTimeData.RePower;
                pd->RealTimeData.ApPower = __ffsqrtf(ftmp);
                pd->RealTimeData.PowerFactor = pd->RealTimeData.AcPower/pd->RealTimeData.ApPower;
                pd->RealTimeData.PhaseAngle = acos(pd->RealTimeData.PowerFactor) * 57.29578f;
                
                pd->Urms2Num = 0;
                pd->Urms2Sum = 0;
                pd->AcPowSum = 0;
                pd->RePowSum = 0;
                pd->PeriodSyn = 0;
                //ESTOP0;
                #endif
            }
        }
    }
}
void UpdatePara2Freq(void)
{
    int16 i;
    float32 ftmp;
    _ChannelData *pd;
    
    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if((pd->CalcConfig & CALC_POWER) == 0)
            continue;
        if((pd->RealTimeData.Frequency > 45.0) && (pd->RealTimeData.Frequency < 55.0))
        {
            //shift90=Fs/f/4
            ftmp = (SAMPLE_F/4.0f) / pd->RealTimeData.Frequency;
            pd->PhaseInt = (int16)(ftmp);
            pd->PhaseFloat = ftmp - pd->PhaseInt;  
            pd->PhaseFloat2 = pd->PhaseFloat * pd->PhaseFloat;
        }
        pd->CalcLen = 160*3;

        //pd++;
    }
}

void SampleIsrProcess(void)
{
    Sample2Buff();
    PhaCalForAc();
    IIRLpfVolt();
    CalcFreq();
    PhaCalForRe();
    ChnConcate();
    IIRLpfPower();
    QuasiFunc();
}
float32 CalcAvgInt(int16 *p, int16 n)
{
    float32 res = 0;
    int16 i;
    int16 *pdata = p;
    for(i = 0; i < n; i++)
    {
        res += *pdata++;
    }
    res /= n;
    return res;
}

float32 CalcAvgFloat(float32 *p, int16 n)
{
    float32 res = 0;
    int16 i;
    float32 *pdata = p;
    for(i = 0; i < n; i++)
    {
        res += *pdata++;
    }
    res /= n;
    return res;
}

void ChnConcate(void)
{
    ChannelData[0].InstanCurr = ChannelData[1].InstanVolt;
}

void CalcChnInit(void)
{
    int16 i;
    _ChannelData *pd;
    

    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        MemSet((Uint16 *)pd, 0, sizeof(_ChannelData));
        pd->pVolt = SMP_NUM-1;
        pd->ZeroStart = ZERO_CNT_CYC+1;
        pd->PhaseInt = 40;
        pd->CalcLen = 160*3;
        pd->FreqChang = 1;
        pd->CalcConfig = CALC_POWER | CALC_FREQUENC | CALC_URMS;
    }
    pd = &ChannelData[1];
    pd->CalcConfig = 0;
    //pd->CalcFlg = CALC_POWER | CALC_URMS;
}
void CalcExec(void)
{
    int i;
    int acdir, redir, q;
    float32 ftmp;
    _ChannelData *pd;
    

    for(i = 0; i < CHN_NUM; i++)
    {
        pd = &ChannelData[i];
        if(pd->UpdataFlg == 1)
        {
            acdir = 0;
            redir = 0;
            ftmp = pd->Urms2Sum/(float32)(pd->Urms2Num);
            ftmp = __ffsqrtf(ftmp);
            pd->RealTimeData.Urms = ftmp;
            pd->RealTimeData.AcPower = pd->AcPowSum/pd->Urms2Num;
            pd->RealTimeData.RePower = pd->RePowSum/pd->Urms2Num;
            //pd->RealTimeData.AcPower = ABS(pd->RealTimeData.AcPower);
            //pd->RealTimeData.RePower = ABS(pd->RealTimeData.RePower);
            ftmp = pd->RealTimeData.AcPower * pd->RealTimeData.AcPower
                + pd->RealTimeData.RePower * pd->RealTimeData.RePower;
            pd->RealTimeData.ApPower = __ffsqrtf(ftmp);
            pd->RealTimeData.PowerFactor = pd->RealTimeData.AcPower/pd->RealTimeData.ApPower;
            pd->RealTimeData.PhaseAngle = acos(ABS(pd->RealTimeData.PowerFactor)) * 57.29578f;
            if(pd->RealTimeData.AcPower < 0)
                acdir = 1;
            if(pd->RealTimeData.RePower < 0)
                redir = 1;
            q = 2 * redir + acdir;
            q = Quadrant[q];
            pd->RealTimeData.PhaseAngle += q;
            pd->Urms2Num = 0;
            pd->Urms2Sum = 0;
            pd->AcPowSum = 0;
            pd->RePowSum = 0;
            

            pd->UpdataFlg = 0;
            
            pd->PeriodSyn = 0;
            
        }
        if(pd->FreqChang == 1)
        {
            UpdatePara2Freq();
            pd->FreqChang = 0;
        }
    }
}
#if 0
void IIRTst(void)
{
    Uint16 j;
    float32 fr = 50.0;

    float32 RadStep; //  2*pi*WAVE_F/SAMPLE_F
    float32 Rad;
    Uint16 p = 0;
    ESTOP0;
    RadStep = 2.0*PI*fr / 8000.0f;
    Rad = 0.0;
    //ZeroStart = ZERO_CNT_CYC+1;
    //ZeroTimer = 0;
    //pVolt = 59;
    for(j = 0; j < 60000; j++)
    {
        #if 0
        for(i = 0; i < 2000; i++)
        {
            VoltSmpBufTmp0[i] = 200*sin((2.0f*PI*fr*((float32)i))/8000.0f)/*+50*sin((2.0f*PI*2*fr*((float32)i))/8000.0f)*/;
           
        }
        #else
        if(j >= 50000)
        {
            j = 0;
        }
        Rad += RadStep;
        if(Rad > 2*PI)
        {
            Rad -= 2*PI;
        }
        WaveTmp = 50*sin(Rad) /*+ 50*sin(5*RadStep*j)*/;
        //VoltSmpBufTmp0[p] = IIRLpf_U_out[0];
        //VoltSmpBufTmp1[p] = WaveTmp;
        p++;
        p %= 2000;
        if(p == 0)
        {
            //ESTOP0;
        }
        SampleIsrProcess();
        #endif
    }
    ESTOP0;
}
#endif


measure.h


#ifndef __MEASURE_H_
#define __MEASURE_H_

#define SMP_NUM    60
#define CHN_NUM    2

typedef struct
{
    float32 Urms;
    float32 Frequency;
    float32 HarmAmp[23];
    float32 HarmFre[23];
    float32 Umax;
    float32 Umin;
    float32 AcPower;
    float32 RePower;
    float32 ApPower;
    float32 PowerFactor;
    float32 PhaseAngle;
    
}_RealTimeData;


typedef struct
{
    float32 VoltSmpBuf[SMP_NUM];
    float32 InstanVolt;
    float32 InstanCurr;
    float32 ShiftPhsVolt;
    float32 Urms2Sum;
    float32 AcPowSum;
    float32 RePowSum;
    float32 AcPowerTmp;
    float32 RePowerTmp;
    float32 PhaseFloat;
    float32 PhaseFloat2;
    float32 IIrForP[3];
    float32 IIrForQ[3];

    int32 IIrForU[3];
    int16 IIrForUout[2];
    int16 pVolt;
    int16 Urms2Num;
    int16 PhaseInt;
    int16 CalcLen;
    
    int16 ZeroTimer;
    volatile int16 FreqChang;
    volatile int16 UpdataFlg;
    volatile int16 ZeroStart;
    volatile int16 PeriodSyn;
    volatile Uint16 CalcConfig;

    _RealTimeData RealTimeData;
    
}_ChannelData;

typedef struct
{
    float32 u1;
    float32 ad1;
    float32 u2;
    float32 ad2;
    float32 k;
    float32 b;
}_CalcCeof;

//extern _RealTimeData RealTimeData;
//extern _ChannelData ChannelData[CHN_NUM];
extern Uint16 HanningWin[1024];
//extern int16 pVolt;
//extern float32 InstanVolt;

//extern volatile int16 PeriodSyn;
extern volatile int16 FFTProc;
extern volatile int16 FFTSmpNum;

float32 VoltRmsCalc(float32 *fdata, int16 n);
void cal_test(void);
float32 Fre2Queue(Uint16 val);
float32 CalcAvgInt(int16 *p, int16 n);
float32 CalcAvgFloat(float32 *p, int16 n);
void Measure_Test(void);
void SysFFTCalc(void);
void SysFFTInit(void);
void AD2RealVal(int16 * psrc, float32 * pdst);
void FFT2Fun(void);
void HarmonicAnalysis(_ChannelData *pd);
void HarmonicProcess(void);
void MakeWave(void);
void CalcFreq(void);
void Sample2Buff(void);
void PhaCalForAc(void);
void IIRLpfVolt(void);
void QuasiFunc(void);
void UpdatePara2Freq(void);
void SampleIsrProcess(void);
void CalcChnInit(void);
void ChnConcate(void);
void CalcExec(void);
void IIRTst(void);


#endif





  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM8S 是一种微控制器系列,它具有模拟到数字转换器(ADC)功能,用于对模拟信号进行采样和转换为数字信号。在STM8S上实现AD采样滤波算法有很多种方法,下面我将介绍一种常见的算法。 第一步是设置ADC的参数。我们可以选择采样速率、参考电压采样分辨率等参数,以适应应用的需求。 第二步是初始化ADC。这包括设置引脚和模式,并启用ADC模块。 第三步是开始AD转换。通过启动ADC转换,并等待转换完成的标志位。 第四步是获取转换结果。读取ADC的数据寄存器,获取转换后的数字值。 第五步是进行滤波。我们可以使用不同的滤波算法来处理采样数据,如移动平均滤波、中值滤波或卡尔曼滤波等。这些算法可以根据应用的需求选择适当的方法。 最后一步是根据需要重复以上步骤。我们可以设置一个循环来连续进行AD采样和滤波,以获取连续的数据流。 需要注意的是,选择适当的采样速率和滤波算法非常重要。过高的采样速率可能会浪费系统资源,而过低的采样速率可能会导致数据丢失或失真。滤波算法的选择应根据应用的实际需求和性能要求进行权衡。 总结起来,STM8S上的AD采样滤波算法需要经过设置参数、初始化ADC、开始转换、获取结果和滤波处理等步骤,以获取满足应用需求的高质量数字信号。这是一种常见的实现方法,具体的细节会根据具体的应用和系统要求进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值