下面将重点介绍核心函数和算法:1、第一个函数是arm_status arm_cfft_radix4_init_f32(arm_cfft_radix4_instance_f32 * S, uint16_t fftLen,uint8_t ifftFlag,uint8_t bitReverseFlag) 在使用时,这个函数用于初始化 傅里叶变换运算的相关配置。fftLen用于确定FFT变换的长度,其默认有5种不同的设置,分别是(16/64/256/1024/4096)。本系统采用4096点傅里叶变换,故将此设置为4096。ifftFlag这个参数为0或者是1,为0时是傅里叶变换,为1时为傅里叶反变换,系统采用傅里叶变换,固将其配置为0;bitReverseFlag的取值为0或者1,为1时是按位取反,系统配置为1。最后这些参数存储在一个结构体指针S里面。2、第二个函数是void arm_cfft_radix4_f32(const arm_cfft_radix4_instance_f32 * S,float32_t * pSrc) 本系统在计算基-4浮点傅里叶变换运算时就是利用这个函数,通过指针pSrc传入采集到的输入信号数据(实部和虚部形式)。这里要特别注意,输入信号应以复数的形式传入,实部放在奇数位,虚部放在偶数位。进行4096点FFT运算,则pSrc指向4096个复数,实际应用中,系统通过A/D采样,这样偶数位全部为0,奇数位为A/D转换器采集到的电压值。同时FFT变换后的数据也存放在pSrc里面,pSrc必须不小于fftLen的长度。另外,S结构体指针参数是由先该函数设置好,然后传入该函数的。3、第三个函数是void arm_cmplx_mag_f32(float32_t * pSrc,float32_t * pDst,uint32_t numSamples) 系统通过这个函数来计算复数模值,可以对第二个函数* pSrc指向的输出结果进行傅里叶变换进行取模操作。pSrc指向第二个函数傅里叶变换的结果,为复数输入数组指针;pDst为输出数组指针,存储取模后的值;numSamples是进行取模的点数,系统进行4096点的傅里叶变换,在此配置为4096即可。 为了验证算的可靠性,我们可以通过模拟生成输入序列的方式进行验证。for(i=0;i
上段代码就是模拟生成一个序列。原始信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。 通过测试,可以发现,系统计算4096点的傅里叶变换需要的时间仅仅只要2.71ms,可见其速度是非常快。在傅里叶变换的输出中,我们可以发现只有在Outputbuf[0]、Outputbuf[1]、Outputbuf[4]、Outputbuf[8]处傅里叶变换的结果分别为4096、2048、6144、10240;Outputbuf[4088]、Outputbuf[4092]、Outputbuf[4095]处的值分别为10240、6144、2048。下面来分析这些结果。 模拟的采样频率为40960Hz,采样的点数为4096,由数字信号处理知识可知,分辨率为10Hz,也即傅里叶变换计算后的频谱之间的间隔是10Hz。而Inputdata[2*i]=1+1*arm_sin_f32(2*PI*10*i/Fs)+3*arm_sin_f32(2*PI**40*i/Fs)+5*arm_sin_f32(2*PI*80*i/Fs)。可知待测信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。 因为A/D采样后的时序信号为实信号,根据DFT的对称性可知,其傅里叶变换的结果具有共轭反对称性。Outputbuf[1]和Outputbuf[4095],Outputbuf[4]和Outputbuf[4092],Outputbuf[8]和Outputbuf[4088]幅值应该相同,实际情况再次和理论值完全相同。 根据DFT变换后的性质可知:Outputbuf[0]=4096,其傅里叶变换变换后的模值刚好是原始信号的4096倍,所以值为4096.0;而在其它频率点处,模值应该是幅值的4096/2=2048倍,输出的结果刚好为Outputbuf[1]=4096、Outputbuf[4]=2048、Outputbuf[8]=6144与理论值完全相同,可见傅里叶变换运算的精度极高,运算速度极快。下面我们用Matlab验证算法的正确性: Matlab 程序:close all; %Turn off all the pictures
clc;
DC=1; %The magnitude of the dc signal
Amp1=1; %The amplitude of the first signal
Amp2=3; %The amplitude of the second signal
Amp3=5; %The frequency of the third signal
Fre1=10;%The frequency of the first signal )
Fre2=40;%The frequency of the Second signal
Fre3=80;%The frequency of the third signal
Fs=40960; %The sampling frequency
N=4096; %The sampling points
t=[0:1/Fs:1]; %Sampling time
S=DC+Amp1*sin(2*pi*Fre1*t)+Amp2*sin(2*pi*Fre2*t)+Amp3*sin(2*pi*Fre3*t); %信号
%Display the original signal
subplot(3,1,1);
plot(S,'b');
grid on;
xlabel(' Frequency/HZ');
ylabel('Voltage');
title('The original signal');
Y = fft(S,N); %Do FFT transform
Module = (abs(Y)); %:Acquire modulus
subplot(3,1,2);
F=([1:N]-1)*Fs/N;
h = stem(F(1:N/320)/10,Module(1:N/320),'fill','--');
set(get(h,'BaseLine'),'LineStyle',':')
set(h,'MarkerFaceColor','red')
grid on;
xlabel(' FFTout[i]');
ylabel('FFT module');
title('the module value of FFT');
Module=Module/(N/2);
Module(1)=Module(1)/2;
F=([1:N]-1)*Fs/N;
subplot(3,1,3);
h = stem(F(1:N/320),Module(1:N/320),'fill','--');
set(get(h,'BaseLine'),'LineStyle',':')
set(h,'MarkerFaceColor','red')
grid on;
xlabel(' Frequency /HZ');
ylabel('Voltage');
title('Amplitude - frequency curves');
Matlab运行的结果如下所示: 图1 FFT仿真结果 从Matlab仿真出来的结果和理论的结果完全一样。图一为原始的信号,原始信号由三个正弦信号和一个直流信号叠加而成,频率分别是10Hz、40Hz和80Hz,峰值分别为1、3、5,直流分量为1。图二为输入信号进行FFT运算后的输出结果,可以看出在FFTout[1]、FFTout[4]、FFTout[8]处有值,且值得大小和输入信号的幅度有关。图三为将模值化为实际电压值后的结果,可以看出其分别在频率0Hz、10Hz、40Hz、80Hz处的幅值分别为1、1、3、5。 注意事项: