最近复盘了20年电赛E题,基本思路为使用通用定时器3触发ADC采集信号,然后运用官方库处理信号,然后计算THD。比较粗糙,希望大家海涵,后面或许会出更详细教程。
大致说
第一步采集到的信号我们运用官方FFT库函数 cr4_fft_1024_stm32(lBufOutArray,lBufInArray,NPT),其中NPT为采样点数,lBufInArray数组放置的是采集到的信号,需要被处理;lBufOutArray放置的是FFT处理后的信号数组。
#define NPT 1024
/*********************关于ADC的数据定义***************************/
extern u8 ADC_Finsish_Flag; //ADC采集完1024个点的标志位,0未完成,1采集完成
extern uint32_t AD_Data[1024]; //存放ADC采样数据
long lBufInArray[NPT];
long lBufOutArray[NPT/2];
long lBufMagArray[NPT/2];
float PI2=6.28318530717959;
cr4_fft_1024_stm32(lBufOutArray,lBufInArray,NPT);
第二步接下来lBufOutArray进入GetPowerMag()函数计算得各次谐波幅值,各次谐波幅值是用来计算THD的,
void GetPowerMag()
{
int F=10;
signed short lX,lY;
float X,Y,Mag;
unsigned short i;
for(i=0; i<NPT/2; i++)
{
lX = (lBufOutArray[i] << 16) >> 16;
lY = (lBufOutArray[i] >> 16);
X = NPT * ((float)lX) / 32768;
Y = NPT * ((float)lY) / 32768;
Mag = sqrt(X * X + Y * Y) / NPT;
if(i == 0)
lBufMagArray[i] = (unsigned long)(Mag * 32768);
else
lBufMagArray[i] = (unsigned long)(Mag * 65536);
// printf("%d ",i);
// printf("%d ",F*i);
// printf("%ld ",lBufMagArray[i]);
// printf("%d ",lX);
// printf("%d \r\n",lY);
}
}
第三步所以接下来带着lBufMagArray[100](基波),lBufMagArray[200](二次谐波), Uo3=lBufMagArray[300](三次谐波),Uo4=lBufMagArray[400](四次谐波),Uo5=lBufMagArray[500](五次谐波)进入GetTHD函数,计算出THD
double GetTHD()
{
float Uo1,Uo2,Uo3,Uo4,Uo5;
double THD,thd_fz=0,thd_fm=0;
Uo1=lBufMagArray[100];
Uo2=lBufMagArray[200];
Uo3=lBufMagArray[300];
Uo4=lBufMagArray[400];
Uo5=lBufMagArray[500];
//printf("%f\r\n",Uo1);
thd_fm=Uo1;
thd_fz=Uo2*Uo2 + Uo3*Uo3 + Uo4*Uo4 + Uo5*Uo5;
thd_fz=sqrt(thd_fz);
THD=thd_fz/thd_fm*100;
return THD;
}
细说
首先来说第一步,FFT官方库函数需要自己下载并且添加到工程里。有两个库函数,一个是cr4_fft_1024_stm32,一个是cr4_fft_256_stm32,1024和256代表采样点数,一个周期采样点数越多是不是波形就越接近原来的波形更精确呢?所以我们选择1024这个,并且采样点数NPT也就顺理成章用1024。
对于采样频率,定时器频率f=72M/((ARR+1)(PSC+1)),ADC采样频率