信号处理__FFT变换
什么是FFT
快速理解FFT
FFT与卷积(慎入)
FFT(fast Fourier transform),即快速傅里叶变换
多项式点值法:多项式相乘就是对应点值得相乘
graph LR
A[多项式相乘] --> B[多项式系数的卷积]
B -->C[多项式点值法对应点相乘]
B -->D[卷积可以变换到频域进行对应点相乘]
加速离散傅里叶变换(DFT)
卷积当中的频域相乘
双侧FFT和单侧FFT,奎奈斯特采样定理,
什么是傅里叶变换
时域函数 -> 频域函数 就是傅里叶变换
将一个函数变形为几个不同值得三角函数的和的形式
graph LR
A[时域函数] -->|傅里叶变换| B[频域函数]
B -->C[幅度频谱图]
B -->D[相位频谱图]
C -->|反映|E[信号频率特性]
D -->|反映|E
FFT的过程
- 数字化,即采样
块长度,指采样的数量;块长度 -决定-> 频谱分辨率(Δf)
频域弥散(频域泄露),是指采样窗口不能很好的匹配信号周期,导致块之间的跳变,使得频谱峰值弥散
窗函数,用来抑制频域泄露, - DFT转换(FFT算法)
单侧FFT代码
ADC采集详见ADC信号采集
/*********************ADC采集***********************/
HAL_ADCEx_Calibration_Start(&hadc1);
HAL_ADC_Start_DMA(&hadc1, (uint32_t *)adcBuff, FFT_LENGTH);
HAL_TIM_Base_Start(&htim3);
while (!AdcConvEnd);
/**********************傅里叶变换*******************************/
for (int i = 0; i < FFT_LENGTH; i++)
{
//两个元素为1个采样点,前为实部,后为虚部
fft_inputbuf[i * 2] = adcBuff[i] * 3.3 / 4096;//实部赋值,为真实电压
fft_inputbuf[i * 2 + 1] = 0; //虚部赋值,固定为0
}
arm_cfft_f32(&arm_cfft_sR_f32_len1024, fft_inputbuf, 0, 1);//傅里叶变换核心过程
arm_cmplx_mag_f32(fft_inputbuf, fft_outputbuf, FFT_LENGTH); //变换结果复数求模得到幅值
/**********************结果处理*******************************/
/*
归一化处理,恢复原始信号中的分量的幅度
第0位为直流分量(即与w无关的常数项),幅度是原始信号中直流分量的N倍(N=1024)
交流分量的幅度是原始信号中该频率分量幅度的N/2倍
*/
fft_outputbuf[0] /= 1024;
for (int i = 1; i < FFT_LENGTH; i++)
{
fft_outputbuf[i] /= 512;
}
/***********************输出幅度结果**********************************/
printf("FFT Result:\r\n");
for (int i = 0; i < FFT_LENGTH; i++)
{
printf("%d:\t%.2f\r\n", i, fft_outputbuf[i]);
}
[学习文章](https://blog.csdn.net/qq_34022877/article/details/117855263)
跟着文章做完后编译会报错error: #101,以下是我对博主配置的修改:
- 添加宏
ARM_MATH_CM4 //F4是这个
ARM_MATH_MATRIX_CHECK
ARM_MATH_ROUNDING - 移除 ST 提供的 DSP 库
1.在工程中排除 ST 的 DSP 文件:
在 Keil 的 Project 面板中,找到 Middlewares/ST/ARM/DSP 组。
右键点击该组 → 选择 "Options for Group 'DSP'"。
取消勾选 "Include in Target Build" → 点击 OK。
2.删除包含路径:
打开工程选项(Alt+F7)→ "C/C++" 选项卡 → "Include Paths"。
移除指向 ST DSP 库的路径(如 ../Middlewares/ST/ARM/DSP/Inc)。
3.使用 Keil 自带的 CMSIS-DSP:
确保在代码中只包含标准路径:#include <arm_math.h>

浙公网安备 33010602011771号