打印
[STM32]

请教:Cortex-M单片机使用CMSIS-DSP库做FFT,FLASH占用的问题

[复制链接]
8138|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 jiangjiayu 于 2018-1-24 11:41 编辑

最近要用到FFT,开始用 arm_cfft_q31 很好用速度也很快,但是输出结果有“镜像”
如下图所示,,,也就是:采样256个点,取模输出128个点(送去上位机显示),结果只有64个点可用,岂不是很坑

于是
现在改用arm_rfft_q31,需要一个arm_rfft_init_q31函数 来初始化,结果,我一加入arm_rfft_init_q31函数 编译后的FLASH就占用130K+,请问这个正常吗?如何减小?



CMSIS-DSP库版本如下:
* $Date:        20. October 2015
* $Revision:    V1.4.5 b

感谢

2018/01/24更新
1.“镜像”问题已经解决,见10楼,原因是输入不正确
2. arm_rfft_init_q31占用内存大原因见14楼,原因是查表,放入了大量表格




相关帖子

沙发
ayb_ice| | 2018-1-23 08:56 | 只看该作者
我最近也在搞这个,据说是对称的,就是是只用前半部分

使用特权

评论回复
板凳
ayb_ice| | 2018-1-23 08:57 | 只看该作者
m3没有硬件浮点,代码大些也是正常的,不过这个确实有点大

使用特权

评论回复
地板
jiangjiayu|  楼主 | 2018-1-23 09:12 | 只看该作者
ayb_ice 发表于 2018-1-23 08:57
m3没有硬件浮点,代码大些也是正常的,不过这个确实有点大

对啊,这也太大了,M0的库也一样,也很大
第一个是对称的,没办法解决了吧估计?

使用特权

评论回复
5
ayb_ice| | 2018-1-23 09:42 | 只看该作者
jiangjiayu 发表于 2018-1-23 09:12
对啊,这也太大了,M0的库也一样,也很大
第一个是对称的,没办法解决了吧估计? ...

但你的对称有点不对吧

好像是这样的,

如果采样256点,则输入缓冲区大小是256*2,输出缓冲区是256*1,有效输出是256/2

代码大小估计没办法了,可能是内部使用了查表什么的

使用特权

评论回复
评论
jiangjiayu 2018-1-23 13:02 回复TA
如果输入缓冲区是2*256,采样256点,那另一个256填充0吗?还是怎么样呢? 我看了库的源码,确实是查表的,精简了一些没用的也是60K+,没办法了 
6
jiangjiayu|  楼主 | 2018-1-23 13:03 | 只看该作者
本帖最后由 jiangjiayu 于 2018-1-23 13:05 编辑
ayb_ice 发表于 2018-1-23 09:42
但你的对称有点不对吧

好像是这样的,

如果输入缓冲区是2*256,采样256点,那另一个256填充0吗?还是怎么样呢???? ////////////////////   我看了库的源码,确实是查表的,精简了一些没用的也是60K+,没办法了
欢迎探讨~~

使用特权

评论回复
7
ayb_ice| | 2018-1-23 13:21 | 只看该作者
jiangjiayu 发表于 2018-1-23 13:03
如果输入缓冲区是2*256,采样256点,那另一个256填充0吗?还是怎么样呢???? ////////////////////    ...

输入数据是复数形式,一个输入AD值,一个填0,这样循环。。。

使用特权

评论回复
8
jiangjiayu|  楼主 | 2018-1-23 13:50 | 只看该作者
ayb_ice 发表于 2018-1-23 13:21
输入数据是复数形式,一个输入AD值,一个填0,这样循环。。。

arm_cfft_q31(&arm_cfft_sR_q31_len128, <font color="#0000ff">testInput</font>, ifftFlag, doBitReverse);
int32_t  testInput[256];  //输入缓冲输入256个点,是这样的哦,我现在做的是输入缓冲内AD采样256个点,然后FFT
虚数是怎样输入的呢?

使用特权

评论回复
9
ayb_ice| | 2018-1-23 14:08 | 只看该作者
本帖最后由 ayb_ice 于 2018-1-23 14:10 编辑
jiangjiayu 发表于 2018-1-23 13:50
int32_t  testInput[256];  //输入缓冲输入256个点,是这样的哦,我现在做的是输入缓冲内AD采样256个 ...

安装相应的开发库后有例程
C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.11.0\Drivers\CMSIS\DSP_Lib\Examples\arm_fft_bin_example\ARM

ARM.rar

14.47 KB

使用特权

评论回复
10
jiangjiayu|  楼主 | 2018-1-23 15:33 | 只看该作者
ayb_ice 发表于 2018-1-23 14:08
安装相应的开发库后有例程
C:\Keil_v5\ARM\PACK\Keil\STM32F4xx_DFP\2.11.0\Drivers\CMSIS\DSP_Lib\Exampl ...

输入是:实数,虚数,实数,虚数...
虚数保持为0

使用特权

评论回复
11
ayb_ice| | 2018-1-23 16:24 | 只看该作者
jiangjiayu 发表于 2018-1-23 15:33
输入是:实数,虚数,实数,虚数...
虚数保持为0

这方面我也是菜鸟,

使用特权

评论回复
12
yjmwxwx| | 2018-1-23 19:04 | 只看该作者
本帖最后由 yjmwxwx 于 2018-1-23 19:07 编辑
jiangjiayu 发表于 2018-1-23 13:03
如果输入缓冲区是2*256,采样256点,那另一个256填充0吗?还是怎么样呢???? ////////////////////    ...

我自己写过radix-2复数256点M0的程序,我把ADC采样放到缓冲区的虚部,然后位反转后数据就写到实部了,再计算就用虚部数据把ADC的采样覆盖掉了。CMSIS-DSP库M0的Q15radix-2复数FFT看汇编代码有大概700行(不算数组),[size=29.3333px]喵了一眼里面还用了除法,M0没除法指令他还用除法,光除法就30行而且中间还有循环,编译出来不算数组占了大概2K空间,不知道你这个60K是什么占的。

使用特权

评论回复
13
ayb_ice| | 2018-1-24 09:00 | 只看该作者
yjmwxwx 发表于 2018-1-23 19:04
我自己写过radix-2复数256点M0的程序,我把ADC采样放到缓冲区的虚部,然后位反转后数据就写到实部了,再计 ...

请教下位反转怎么用,是什么意思。

使用特权

评论回复
14
jiangjiayu|  楼主 | 2018-1-24 09:10 | 只看该作者
本帖最后由 jiangjiayu 于 2018-1-24 09:26 编辑
yjmwxwx 发表于 2018-1-23 19:04
我自己写过radix-2复数256点M0的程序,我把ADC采样放到缓冲区的虚部,然后位反转后数据就写到实部了,再计 ...


主要是上图两个大表格数据量太大,每个表格都是8192个32bit数,就是下面两个:
static const q31_t realCoefAQ31[8192] = {0x40000000, 0xc0000000, 0x3ff36f02, ... , 0x3ffffec4};
static const q31_t realCoefBQ31[8192] = { 0x40000000, 0x40000000, 0x400c90fe,..., 0xc000013c};

所以占用了60K+的FLASH空间

使用特权

评论回复
15
jiangjiayu|  楼主 | 2018-1-24 09:12 | 只看该作者
本帖最后由 jiangjiayu 于 2018-1-24 09:13 编辑
ayb_ice 发表于 2018-1-24 09:00
请教下位反转怎么用,是什么意思。

有一种位反转是:比如  某个数二进制是 1100 0001 (0xC1)    ,反转后就是 1000 0011 (0x83),这个在FFT好像叫做倒序吧,不知道说的是不是这个

使用特权

评论回复
16
yjmwxwx| | 2018-1-24 12:47 | 只看该作者
ayb_ice 发表于 2018-1-24 09:00
请教下位反转怎么用,是什么意思。

256点的,0到255就是8位二进制数,3就是0000 0011,反转过来就是1100 0000 。
也就是重新排序的意思,把192号这个数据当作3号数据进行蝴蝶运算。

//位反转
#include <stdio.h>
void main() {
        int aa,a2,a3,a4,a5,bb,cc,dd;


        bb=256;                                //长度
        dd=bb;
        for(aa=0;aa<bb;aa++){
                cc=1;
                a3=0;
                a4=a3;
                while(cc<dd){
                a2=aa & cc;
                a5=bb>>1;
                if(a2!=0){
                a5=a5>>a4;
                a3=a3 | a5;
}
                cc=cc<<1;
                a4=a4+1;

       
}
        printf("%d\n",a3);               
}       
}


使用特权

评论回复
17
gujiamao12345| | 2018-1-24 12:54 | 只看该作者
镜像对称是没错的,
但是为毛你的只有四分之一有效

使用特权

评论回复
18
yjmwxwx| | 2018-1-24 12:55 | 只看该作者
jiangjiayu 发表于 2018-1-24 09:10
主要是上图两个大表格数据量太大,每个表格都是8192个32bit数,就是下面两个:
static const q31_t realC ...


没用过库不太清楚,你又不计算8192点的,应该有小的表吧

使用特权

评论回复
19
ayb_ice| | 2018-1-24 13:04 | 只看该作者
yjmwxwx 发表于 2018-1-24 12:47
256点的,0到255就是8位二进制数,3就是0000 0011,反转过来就是1100 0000 。
也就是重新排序的意思,把19 ...

这意思我懂,我是説在FFT中位反转有什么用,不反转可不可以,反转的目的是什么,是提高效率,或者是精度什么的

使用特权

评论回复
20
yjmwxwx| | 2018-1-24 13:10 | 只看该作者
ayb_ice 发表于 2018-1-24 13:04
这意思我懂,我是説在FFT中位反转有什么用,不反转可不可以,反转的目的是什么,是提高效率,或者是精度 ...

这个就不清楚了,具体原理不懂,应该是能减少计算数量吧。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

84

帖子

1

粉丝