(出大问题):

由于在编写的时候忘却了大部分的单片机平台没有对Double(双精度浮点)进行优化,因此运行的时候效率奇低,后续会优化以修正本Bug,加入用户可选的双精度运算,保证在H7等拥有双精度浮点加速的平台有着较好的精度

什么是mcu_fft?

mcu_fft是一款基于C语言的傅里叶变换库,使用快速傅里叶算法进行求解.内置可选用的FIR核心,可以进行滤波运算.

mcu_fft的目的是什么?

提供一个用于单片机(MCU)的FFT库,主要用于实现测量时所需要的变换.

相较于其他的FFT库,mcu_fft的优势是什么?

  • 对平台没有依赖性,对所有的可运行C compiler的平台均可以运行mcu_fft.
  • 提供实际频率(f)频标,节省从数字频率转换为模拟频率的工作

mcu_fft的劣势在哪里?

  • 由于没有针对平台进行优化,在Arm核心的MCU上的性能应最高仅能做到FFT变换的理论性能,也就是时间复杂度为O(nlogn)的运算.
  • 由于本人的能力有限,难免会出现一些奇奇怪怪的Bug,并且功能也并不完善.

    mcu_fft的设计思想

  • 信号链的设计思想,尽可能保证一个函数的输入data在函数运行结束之后更新为data的处理结果,本人比较喜欢这种方法,可以比较清晰的看出信号链的流动方向
  • 当然,这种方法也是有一定的缺点的,在之后的版本中将会对这种方法进行修改,尽可能的兼容多种的处理方法.

让我们开始吧

安装mcu_fft

mcu_fft提供源码,只需要进行解压并引用即可,源码的下载地址如下:
C:https://gitee.com/OliverKung/mcu_fft/raw/master/mcu_fft_c.rar
Cpp: https://gitee.com/OliverKung/mcu_fft/raw/master/mcu_fft_cpp.rar

mcu_fft的文件结构

  • mcu_fft.h
    • mcu_fft_core.c FFT的核心代码
    • mcu_fft_pre.c FFT的前处理代码
    • mcu_fft_aft.c FFT的后处理代码
    • mcu_fft_using.c FFT的实用代码
    • FIR.c FIR的实现代码

mcu_fft的使用

  • mcu_fft_usage
    mcu_fft_usage的声明如下

    void mcu_fft_usage(double data[], double sample_Time, int num_of_pts, double freqMarker[]); 

    使用mcu_fft_usage需要准备以下参量:

    • data[] 存放需要进行FFT的信号序列,double
    • sample_Time 采样周期,double
    • num_of_pts 采样点数量,int
    • freqMarker[] 用于存放频标,double
      值得一提的是,mcu_fft_usage将会进行自动的复数转化,并将最后输出的FFT幅值(绝对值)重新装回data[]当中.后续更新会加入选择功能,可以选择输出的值的类型,包括FFT序列的实部,虚部,幅值等,date:2020.2.12


    • mcu_fft_usage的使用示例
      #define SampleTime 1e-6 //1Msps
      #define Num_of_Pts 4096 //4096pts
      double data[Num_of_Pts]={0};
      double Freq_Mark[Num_of_Pts]={0}; //此处,freqMarker的长度要与采样点数相同,因为二者均为长度为Num_of_Pts的序列
      /*sampling*/
      mcu_fft_usage(data,SampleTime,num_of_pts,Freq_Mark);
      /*output*/

  • mcu_FIR_usage
    mcu_FIT_usage的声明如下

    void mcu_FIR_usage(double data[], double FIR[], int signal_length, int FIR_length, int times);

    使用该函数需要准备以下参量:

    • data[] 信号序列,double
    • FIR[] 滤波器的单位脉冲响应序列,double
    • signal_length&FIR_length 分别存储信号序列长度和FIR脉冲响应序列长度
    • times 这里的times是用于放大进行计算的,由于我们使用Matlab的FDAtools(在较新版本的Matlab中,这项功能被重新命名为Filter Designer)生成的序列会出现很小的响应值,使用这种方式对序列进行优化,可以一定程度上优化精度

      FDAtools/Filter Designer

      与mcu_fft_usage()类似, mcu_FIR_usage()同样会将滤波后的结果重新装回data[]内.


    • 该函数的使用示例
      double FIR_Sequence[] = { 1.59580293420777e-05,-0.000546752692664573,
      0.0011539697641281,-0.00165186352705445,0.00136270810593162,
      0.000301689639400425,-0.00336736150662413,0.0068516837425501,
      -0.00875374001783947,0.00673016832708933,0.000624636982277882,
      -0.012389500474644,0.0245743565399063,-0.030678590719918,
      0.0237063633495183,0.0009328600206886,-0.0427953869544021,
      0.0953194930896113,-0.147052050766303,0.184999634419181,
      0.801061092948126,0.184999634419181,-0.147052050766303,
      0.0953194930896113,-0.0427953869544021,0.0009328600206886,
      0.0237063633495183,-0.030678590719918,0.0245743565399063,
      -0.012389500474644,0.000624636982277882,0.00673016832708933,
      -0.00875374001783947,0.0068516837425501,-0.00336736150662413,
      0.000301689639400425,0.00136270810593162,-0.00165186352705445,
      0.0011539697641281,-0.000546752692664573,1.59580293420777e-05 };//这里我们定义了一个40阶的LPF@400KHz
      double data[Num] = { 0 };
      /*sampling*/
      mcu_FIR_usage(data_af_FIR, FIR_Sequence, Num, 41, 32768);//常用32768作为Times

      目前的已知Bug

  • 目前最大的问题就是在分辨率上,由于分辨率的问题,对于频率来说有着较好的分辨率,但是对于幅度来说个人感觉有较大的问题.具体的幅度准确性目前尚待探讨.但是不是很准的样子
最后修改日期:2021年12月7日