基于STM32F407实现快速傅里叶变化(FFT),计算指定频率的幅值

本人的课题是关于EIT采集系统,简单的说就是往人体注入特定频率的恒流源,再采集电压信号,通过分析电阻抗分布进行成像。采集的电压信号是需要进行FFT处理,只保留注入频率的信号成分。本文主要介绍如何在STM32F407上实现对特定频率进行FFT。

关于快速傅里叶变化这里不做过多的介绍,具体可参考别人写的博客:

如何 FFT(快速傅里叶变换) 求幅度、频率(超详细 含推导过程)_Xav Zewen的博客

  1. 使用DSP库进行FFT计算

1.1 DSP库开启

STM32F407是具有浮点运算(FPU)功能,可以通过MDK配置:target->Roating Point Hardware->Use Single Precison中打开。

同时在MDK配置中添加头文件:ARM_MATH_CM4

添加dsp数学库,由此就可以调用DSP库中的函数。

1.2 调用DSP库进行FFT计算

EIT的正弦激励电压为97.656kHz,经测试ADC的采样频率为8.3333MHz,采样512个数据点,取N=6(第7个数据点),即经FFT变换后的第7个数据点为97.656kHz频率成分的幅值。

FFT变换相关的代码如下:

    float array_f32[512];               //储存每次采集的512点位数据(定义为全局变量)
    float array_FFT_output[512];        //储存FFT变换后的512个数据
    float array_arm_cmplx_mag[512];     //储存FFT变换后的512个数据的幅值信息

    arm_rfft_fast_instance_f32 S;
    arm_rfft_fast_init_f32(&S, fftSize);        //初始化结构体S中的参数
    arm_rfft_fast_f32(&S, array_f32, array_FFT_output, 0);          //fft正变换    
    arm_cmplx_mag_f32(array_FFT_output, array_arm_cmplx_mag, 512);    
    
    /*------------ 保存FFT变换后的第7个数值 -----------------*/    
    eit_fft_result[num_EIT_208] = array_arm_cmplx_mag[6];

经测试,采集并计算一帧数据的时间为73ms,还不能达到EIT一秒20帧的采集要求。

  1. FFT计算优化

考虑到我们只需要激励频率的电压幅值,其余频率成分对于我们来说是无效数据。由此,可以单独计算97.656kHz的频率成分,即只计算第7个点位的数据。

离散型傅里叶变化的计算公式如下:

取N=512,k=6,代入可求得第7个点位的数据,计算的代码如下:

float EIT_FUN_FFT(float *FFT_data, float N)
{
        unsigned int i;
        float SUM_Re = 0;        //实频数值
        float SUM_Im = 0;        //虚频数值
        float A = 0;            //幅值
        float k = 6;            //第七个点位数据
        
        //FFT展开式
        for(i=0;i<512;i++)
        {
            SUM_Re = SUM_Re + FFT_data[i]*cos(2*3.1415926*K*i/N);
            SUM_Im = SUM_Im - FFT_data[i]*sin(2*3.1415926*K*i/N);
        }

        //计算幅值
        A = sqrt(SUM_Re*SUM_Re + SUM_Im*SUM_Im);
        
        return A;
}

考虑到cos(2*3.1415926*K*i/N)和 sin(2*3.1415926*K*i/N) 的计算结果是固定值,不会因为ADC采集电压的不同而改变,由此,可以提前计算出N=512,k=6,i取0~511时的cos和sin的计算结果并储存起来,通过查询计算结果替代耗时的三角函数计算,以达到节省计算时间的效果。经过测试,新FFT算法采集一帧的时间为29ms,已能实现一秒30帧的采样要求。

物联沃分享整理
物联沃-IOTWORD物联网 » 基于STM32F407实现快速傅里叶变化(FFT),计算指定频率的幅值

发表评论