|
这篇文章将来测评HC32F448的DSP库和FFT
HC32F448内核集成了FPU和DSP,支持完整DSP指令集,我们将用此进行FFT分析,关于FFT及傅里叶变换的相关知识,这里强烈推荐安富莱的《安富莱_STM32-V7开发板_第2版DSP数字信号处理教程(V2.7)》写的非常详细,非常好,给硬汉哥的开源精神点一个大大的赞
要使用DSP,要进行以下配置。
1、添加DSP库,这里我们可以通过CMSIS来配置,比较方便,这里使用的是1.8.0版本
2、然后点击魔术棒进行如下配置,要使能FPU,这样添加进来的lib就是arm_cortexM4lf_math.lib
4、添加对应的宏定义,使能FPU等功能,可以这么写 HC32F448,USE_DDL_DRIVER,__DEBUG,__TARGET_FPU_VFP,__FPU_PRESENT
5、修改stack的大小,stack负责存放函数的参数值,局部变量的值等,由编译器自动分配释放,具体的技术细节可以参考网络,这里就不再说了。因为FFT会涉及到比较多的参数传递和局部变量(我认为),所以要分配比较大的stack,具体是在startup_hc32f448.s进行修改,那具体要给多大呢,这里我自己的一个方法可以参考,不一定权威(参考正点原子的《MAP文件浅析》),但经过测试确实有用。我们在生成的工程里找到output文件夹,里面有 htm 文件,选择那个不是build_log的文件,我这里是Demo.htm
其包含了它是编译器在编译代码的时候生成的一个列表文件,包含了整个工程的静态调用图,最大的用处就是可以查看栈深度(最小深度),方便设置栈大小。可以直接由浏览器打开。
可以看到,程序的最大栈深度是17088字节,最大栈深时的调用关系为main ⇒ AdcPolling ⇒ FFT ⇒ arm_rfft_fast_f32 ⇒ arm_cfft_f32 ⇒ arm_cfft_radix8by4_f32 ⇒ arm_radix8_butterfly_f32 这也符合常理
不过需要注意的是,这里的最大栈深度仅仅是最低要求(静态栈),因为它并没有统计无栈深的函数(用内存管理)、递归函数、以及无法追踪的函数(函数指针)等所包含的栈(Stack)。
不过它给我们指明了最低需求,我们在分配栈深度的时候,就可以参考这个值来做设置,一般要高于静态栈不少。
我这里设置的FFT点数为4096,这种情况下stack应该是最多的,所以我这里就设置stack为Stack_Size EQU 0x00005000,有20KB这样在点数取小于4096时,stack也都是足够的。如果运行过程中发现程序卡死,出现HardFault_Handler,可能就是这个设置太小了,至少我遇到的是这种情况。
配置好以后,接下来是程序。
这里的程序比较简单,这里就不在赘述了,因为FFT具有对称性,所以最后输出的结果可以只取一半(主要不取一半的话会有问题,目前没法解决)
接下来验证一下,生成一个sin序列,包含一个直流分量,100Hz,200Hz,500Hz的波形,采样率为1024,具体如下
Input_Data_f32 =1+sin(2*3.141592f*100*i/FFT_N)+sin(2*3.141592f*200*i/FFT_N)+sin(2*3.141592f*500*i/FFT_N);
通过串口打印数据,下图是它具体波形
然后将其FFT分解,因为采样率为1024,点数为1024,所以其分辨率为1Hz,就是每一个数据就代表一个频率,下图中第1点,第100点 第200点 第500点有尖峰,说明其中含有对应频率的波形,与输入的原始波形所包含的频率一致,FFT正确。