快速入门 FFT

本文为快速傅里叶变换(FFT)的入门教程,适用于希望实现FFT但不深入研究原理的读者。FFT是数字信号处理中的关键算法,通过特定方法减少了计算复杂度,由DFT的N²级别降低到对数级别。文中介绍了FFT的基本思想,包括数据的奇偶拆分和单位根特性,并展示了两个版本的Python实现,包括对输入数据的预处理以确保正确的输出顺序。尽管存在精度问题,但该实现为理解和应用FFT提供了一个起点。

快速入门 FFT

本文适合不想完全了解 FFT 原理不过想实现 FFT 算法的人

FFT 简介

FFT 也就是常说的快速傅里叶变换,其实本质上和傅里叶变换没有什么不同,也就是通过算法减少了一些乘法和加法的运算;DFT 的时间复杂度是 N² 级别的,而 FFT 的却是对数级别的复杂度,从而在 FFT 在数据量大的时候运算时间并不会高太多,这就使得 FFT 具有了在工程上的使用价值

FFT 算法简介

在这里插入图片描述

上面这张图是来自维基的介绍,简单来说的话,FFT 将数据按照索引地址按奇数和偶数分为两半,这两半数据还可以继续抽取,直到最后分解为单独的数据;然后利用了单位根的一些特性,减少了一些乘加步骤

但是顺序输入的数据,最后得到的结果是乱序的;为了得到顺序的输出,一般我们会将输入数据提前进行整理;因为 FFT 的输出索引地址会位反转,可以利用这个特性提前整理好输入数据,例如:输入 [1 2 3 4 5 6 7 8] 就整理为 [1 5 3 7 2 6 4 8]

FFT 第一个版本实现

最开始我为了能弄懂 FFT ,我就通过手算来了解 FFT 的过程,也就是通过上面那张图中的公式,一级级计算 FFT 的结果

最后根据手算的步骤实现了下面这个版本,其中单位根的复指数计算就直接手动计算完存表表了,在实现后发现只能够适用 4 个数的输入

import cmath

table = [1+0j,2+0j,3+0j,4+0j]
rotate_table = [1+0j,0-1j,-1+0j,0+1j]
result = []

N = 4
k = 0
r = 0
tmp = 0
while k < len(table):
    while r < len(table)/2
### STM32 FFT 快速入门教程 #### 1. 准备工作 为了在STM32上实现FFT算法,首先需要准备必要的硬件和软件环境。推荐使用STM32F103系列微控制器作为实验平台[^1]。对于开发工具的选择,建议采用ST官方提供的STM32CubeMX进行初始化设置以及HAL库的集成。 #### 2. 初始化配置 利用STM32CubeMX完成项目的基础设定,包括但不限于系统时钟、外设(如定时器用于触发ADC采样)、串口通信等功能模块的开启与参数调整。特别注意,在此阶段应确保启用了DMA功能来提高数据传输效率,并设置了合适的中断机制以便及时响应外部事件[^4]。 ```python // 使用CubeMX生成初始化代码框架 ``` #### 3. ADC采集 接下来重点在于如何高效地获取模拟输入信号并将其转化为数字形式供后续处理。这里可以通过编程控制内部模数转换器(ADC),按照预定的时间间隔连续读取电压水平变化情况。考虑到实时性的需求,最好借助于DMA通道自动搬运大量样本至内存缓冲区中等待进一步计算。 ```c /* 设置ADC参数 */ void MX_ADC_Init(void){ // ... (省略部分无关代码) hadc.Instance = ADC1; hadc.Init.ScanConvMode = DISABLE; // 单次模式 hadc.Init.ContinuousConvMode = ENABLE; // 连续转换模式 hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = 1; HAL_ADC_Start_DMA(&hadc, (uint32_t*)aBuffer, BUFFER_SIZE); } ``` #### 4. 实现FFT算法 当拥有了足够的原始数据之后,则可着手编写核心逻辑——即执行离散傅立叶变换(DFT)或其优化版本快速傅立叶变换(FFT)。由于直接运算DFT复杂度较高,因此通常会选择更高效的Cooley-Tukey FFT算法来进行频域分析。具体来说就是通过对时间序列施加特定的操作得到对应的频率成分分布图谱。 ```c #include "arm_math.h" #define N 64 /* 数据长度 */ float32_t input[N]; // 输入数组 float32_t output_real[N]; // 输出实部 float32_t output_imag[N]; // 输出虚部 int main(){ arm_rfft_instance_f32 S; arm_rfft_init_f32(&S,N,0); // 初始化RFFT实例 while(1){ // 填充input[]... arm_cfft_radix4_f32(&S,input,output_real,output_imag); // 处理output_real[], output_imag[] } } ``` #### 5. 结果展示 最后一步便是将经过变换后的数值呈现出来,比如绘制柱状图表示不同频率下的振幅大小关系,从而直观反映出声音特征或是其他周期性现象的存在形态。如果目标应用涉及到音频领域的话,那么还可以考虑构建一个简易版的音乐频谱显示器[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值