我需要在STM32F446微控制器上对8192 个样本块执行FFT。为此,我想使用CMSIS DSP 库,因为它很容易获得并且针对 STM32F4 进行了优化。
我的 8192 个输入样本最终将是来自内部 12 位 ADC 的值(左对齐并通过翻转符号位转换为 q15)。但出于测试目的,我正在为 FFT 提供测试缓冲区。
使用 CMSIS 的 FFT 函数,只有 Q15 版本支持 8192 的长度。因此我使用arm_rfft_q15()。
因为 CMSIS 库的 FFT 函数默认包含大约 32k 的 LUT——为了适应许多 FFT 长度,我已经“重写”它们以删除与我感兴趣的长度不同的所有表。我没有除了删除无用的代码之外,t 触及任何东西。
我的样本存储在我通过 DMA 访问的外部 SDRAM 上。
使用 FFT 时,我有几个问题:
- 我的源缓冲区和目标缓冲区都被修改了;
- 结果完全不像预期的那样
为了确保我得到错误的结果,我在 FFT 之后立即进行了 IFFT,但它只是确认代码不起作用。
这是我的代码:
status_codes FSM::fft_state(void)
{
// Flush the SDRAM section
si_ovf_buf_clr_u16((uint16_t *)0xC0000000, 8192);
q15_t* buf = (q15_t*)(0xC0000000);
for(int i = 0; i<50; i++)
buf[i] = 0x0FFF; // Fill the buffer with test vector (50 sp gate)
// initialise FFT
// ---> Forward, 8192 samples, bitReversed
arm_rfft_instance_q15 S;
if(arm_rfft_init_q15(&S, 8192, 0, 1) != ARM_MATH_SUCCESS)
return state_error;
// perform FFT
arm_rfft_q15(&S, (q15_t*)0xC0000000, (q15_t*)0xC0400000);
// Post-shift by 12, in place (see doc)
arm_shift_q15((q15_t*)0xC0400000, 12, (q15_t*)0xC0400000, 16384);
// Init inverse FFT
if(arm_rfft_init_q15(&S, 8192, 1, 1) != ARM_MATH_SUCCESS)
return state_error;
// Perform iFFT
arm_rfft_q15(&S, (q15_t*)0xC0400000, (q15_t*)0xC0800000);
// Post shift
arm_shift_q15((q15_t*)0xC0800000, 12, (q15_t*)0xC0800000, 8192);
return state_success;
}
这是结果(来自 GDB)
PS:我正在使用ChibiOS - 不确定它是否相关。