嵌入式开发:傅里叶变换(4): STM32上面实现FFT(基于STM32L071KZT6 HAL库+DSP库)

目录

1. 准备工作

2.函数介绍

1. arm_rfft_instance_f32 结构体

2. arm_rfft_fast_init_f32 函数

3. arm_rfft_fast_f32 函数

4. FFT 的执行过程

4. 编写 FFT 实现代码

4.1 初始化 FFT 实例

4.2 配置 FFT 长度和初始化实例

4.3 填充输入数据

4.4 执行 FFT

4.5 处理结果

5. 主函数

6. 编译和调试

7. 总结


在 STM32 上使用 CMSIS-DSP 库实现快速傅里叶变换(FFT),通过以下步骤来实现。CMSIS-DSP 库提供了一系列函数用于处理数字信号,包括 FFT 函数。

1. 准备工作

参考博客:嵌入式开发:傅里叶变换(4):在 MDK 上面移植 DSP 库(基于STM32L071KZT6 HAL库)-优快云博客

2.函数介绍

在 CMSIS-DSP 库中,arm_rfft_instance_f32 和相关的 FFT 函数是用于执行快速傅里叶变换(FFT)的重要组件。这些函数针对 ARM Cortex-M 系列处理器进行了优化,可以高效地执行频域分析。

1. arm_rfft_instance_f32 结构体

arm_rfft_instance_f32 是一个结构体,专门用于存储执行实数快速傅里叶变换(RFFT)所需的参数和配置。这个结构体定义了 FFT 的配置,例如变换的长度、算法类型等。

结构体定义:

typedef struct
{
    uint32_t fftLen;          /**< FFT 数据长度 */
    uint32_t ifftFlag;        /**< 逆向变换标志,0 表示正向,1 表示逆向 */
    uint32_t bitReverseFlag;  /**< 位反转标志,控制是否使用位反转 */
    float32_t *pTwiddle;      /**< Twiddle 因子数组 */
    float32_t *pBitRevTable;  /**< 位反转表 */
} arm_rfft_instance_f32;
  • fftLen:FFT 的长度,决定了处理的数据点数。常见的值是128、 256、512、1024 等。
  • ifftFlag:设置是否进行逆 FFT。0 表示正向 FFT,1 表示逆向 FFT。
  • bitReverseFlag:是否进行位反转。位反转通常用于优化 FFT 的计算。
  • pTwiddle:Twiddle 因子数组,包含了在计算 FFT 时需要用到的复数因子。
  • pBitRevTable:位反转表,用于在进行 FFT 计算时,按照位反转的顺序排列输入数据。
2. arm_rfft_fast_init_f32 函数

arm_rfft_fast_init_f32 用于初始化一个 arm_rfft_instance_f32 结构体,使其准备好执行 FFT。

函数声明:

arm_status arm_rfft_fast_init_f32(
    arm_rfft_instance_f32 *S, 
    uint32_t fftLen
);
  • S:指向 arm_rfft_instance_f32 结构体的指针,函数将会用它来存储 FFT 的配置。
  • fftLen:FFT 的长度(数据点数),必须是 2 的幂(如 256、512、1024 等)。

函数功能:

该函数为给定的 arm_rfft_instance_f32 结构体分配内存并初始化必要的参数,准备好执行 FFT。它会生成 Twiddle 因子和位反转表。

3. arm_rfft_fast_f32 函数

arm_rfft_fast_f32 是执行快速实数傅里叶变换的核心函数。

函数声明:

void arm_rfft_fast_f32(
    const arm_rfft_instance_f32 *S, 
    float32_t *pSrc, 
    float32_t *pDst, 
    uint8_t ifftFlag
);
  • S:指向 arm_rfft_instance_f32 结构体的指针,包含了 FFT 的配置。
  • pSrc:指向输入数据的指针,数组必须包含 fftLen 个数据点。对于正向变换,数据通常是时域数据。
  • pDst:指向输出数据的指针,FFT 结果将存储在这里。数组的大小应为 fftLen
  • ifftFlag:是否进行逆变换。0 表示正向 FFT,1 表示逆向 IFFT。

函数功能:

该函数执行快速傅里叶变换(FFT)。它将 pSrc 中的时域数据转换为频域数据,结果存储在 pDst 中。

4. FFT 的执行过程

一般来说,执行 FFT 的步骤如下:

  1. 初始化 FFT 配置: 使用 arm_rfft_fast_init_f32  来初始化一个 FFT 实例,这样你可以在后续步骤中执行 FFT。

  2. 准备输入数据: 输入数据(如时域信号)需要存放在 pSrc 数组中。

  3. 执行 FFT: 调用 arm_rfft_fast_f32 函数执行 FFT。这个函数会将时域数据转换为频域数据。

  4. 处理 FFT 结果: 使用 arm_cmplx_mag_f32 来计算频域数据的幅度,或者通过分析 pDst 中的实部和虚部来提取频域信息。

4. 编写 FFT 实现代码

4.1 初始化 FFT 实例

首先,我们需要创建并初始化 arm_rfft_instance_f32 结构体,这是用于 FFT 计算的实例。

#include "arm_math.h"  // 包含 CMSIS-DSP 库

#define FFT_SIZE 512 // 设置 FFT 的长度

// 输入数据(时间域数据)
float32_t inputData[FFT_SIZE];

// 输出数据(频域数据)
float32_t outputData[FFT_SIZE];

// 初始化 RFFT 实例
arm_rfft_instance_f32 S;
4.2 配置 FFT 长度和初始化实例

初始化 arm_rfft_instance_f32 实例,并设置 FFT 的长度。

void FFT_Init(void)
{
    // 初始化 FFT 实例,指定 FFT 长度和是否为逆变换(0 表示正变换)
    arm_rfft_fast_init_f32(&S, FFT_SIZE);
}
4.3 填充输入数据

在实际应用中,inputData 数组将包含你要进行 FFT 变换的时间域数据。这里,我们模拟一些输入数据:

void GenerateInputData(void)
{
    // 模拟生成一些数据(例如,一个简单的正弦波)
    for (int i = 0; i < FFT_SIZE; i++)
    {
        inputData[i] = arm_sin_f32(2 * 3.14159f * i / FFT_SIZE);  // 生成正弦波
    }
}
4.4 执行 FFT

调用 arm_rfft_fast_f32 函数进行 FFT 计算。

void PerformFFT(void)
{
    // 执行 FFT 变换
    arm_rfft_fast_f32(&S, inputData, outputData, 0);  // 0 表示正向 FFT
}
4.5 处理结果

FFT 的结果将存储在 outputData 数组中。通过计算输出的幅度或相位来分析频域信息:

void ProcessResults(void)
{
    // 计算每个频率点的幅度
    float32_t magnitude[FFT_SIZE];
    arm_cmplx_mag_f32(outputData, magnitude, FFT_SIZE);
    
    // 输出幅度(仅做示例,可以输出到调试终端等)
    for (int i = 0; i < FFT_SIZE; i++)
    {
        printf("Magnitude[%d] = %f\n", i, magnitude[i]);
    }
}

5. 主函数

将所有步骤结合起来,构成一个完整的程序。

#include "stm32f4xx_hal.h"
#include "arm_math.h"

#define FFT_SIZE 256

float32_t inputData[FFT_SIZE];
float32_t outputData[FFT_SIZE];
arm_rfft_instance_f32 S;

void FFT_Init(void)
{
    // 初始化 FFT 实例
    arm_rfft_fast_init_f32(&S, FFT_SIZE);
}

void GenerateInputData(void)
{
    for (int i = 0; i < FFT_SIZE; i++)
    {
        inputData[i] = arm_sin_f32(2 * 3.14159f * i / FFT_SIZE);  // 生成正弦波
    }
}

void PerformFFT(void)
{
    // 执行 FFT 变换
    arm_rfft_fast_f32(&S, inputData, outputData, 0);  // 0 表示正向 FFT
}

void ProcessResults(void)
{
    float32_t magnitude[FFT_SIZE];
    arm_cmplx_mag_f32(outputData, magnitude, FFT_SIZE);
    
    // 输出幅度
    for (int i = 0; i < FFT_SIZE; i++)
    {
        printf("Magnitude[%d] = %f\n", i, magnitude[i]);
    }
}

int main(void)
{
    // HAL 初始化
    HAL_Init();
    
    // 初始化 FFT
    FFT_Init();
    
    // 生成输入数据
    GenerateInputData();
    
    // 执行 FFT
    PerformFFT();
    
    // 处理结果
    ProcessResults();
    
    while (1)
    {
        // 无限循环,等待调试或者其他操作
    }
}

6. 编译和调试

  1. 编译并下载程序到 STM32 开发板。
  2. 使用调试工具查看 outputData 数组中的结果,或者通过串口输出幅度数据。
  3. 检查输出数据的幅度,并根据需要进行频域分析。

7. 总结

  • CMSIS-DSP 库提供了强大的信号处理功能,使用 arm_rfft_fast_f32 可以非常方便地进行快速傅里叶变换。
  • 通过上述步骤,可以轻松地在 STM32 上实现傅里叶变换并进行频域分析。
  • 根据实际应用,调整输入数据和 FFT 的长度,进一步优化性能。
  • 接下来用FFT对磁通门传感器采集的数据进行滤波处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魂兮-龙游

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值