历史上的今天
返回首页

历史上的今天

今天是:2025年03月16日(星期日)

正在发生

2021年03月16日 | 如何使用STM32提供的DSP库进行FFT

2021-03-16 来源:eefocus

1.FFT运算效率


使用STM32官方提供的DSP库进行FFT,虽然在使用上有些不灵活(因为它是基4的FFT,所以FFT的点数必须是4^n),但其执行效率确实非常高效,看图1所示的FFT运算效率测试数据便可见一斑。该数据来自STM32DSP库使用文档。



图1FFT运算效率测试数据


由图1可见,在STM32F10x系列处理器上,如果使用72M的系统主频,进行64点的FFT运算,仅仅需要0.078ms而已。如果是进行1024点的FFT运算,也才需要2.138ms。


2.如何使用STM32提供的DSP库函数


2.1下载STM32的DSP库


大家可以从网上搜索下载得到STM32的DSP库。


2.2添加DSP库到自己的工程项目中


下载得到STM32的DSP库之后,就可以将其添加到自己的工程项目中了。


其中,inc文件夹下的stm32_dsp.h和table_fft.h两个文件是必须添加的。stm32_dsp.h是STM32的DSP库的头文件。


src文件夹下的文件可以有选择的添加(用到那个添加那个即可)。因为我只用到了256点的FFT,所以这里我只添加了cr4_fft_256_stm32.s文件。添加完成后的项目框架如图2所示。



2.3模拟采样数据


根据采样定理,采样频率必须是被采样信号最高频率的2倍。这里,我要采集的是音频信号,音频信号的频率范围是20Hz到20KHz,所以我使用的采用频率是44800Hz。那么在进行256点FFT时,将得到44800Hz/256=175Hz的频率分辨率。


为了验证FFT运算结果的正确性,这里我模拟了一组采样数据,并将该采样数据存放到了long类型的lBufInArray数组中,且该数组中每个元素的高16位存储采样数据的实部,低16位存储采样数据的虚部(总是为0)。


为什么要这样做呢?是因为后面要调用STM32的DSP库函数,需要传入的参数规定了必须是这样的数据格式。


下面是具体的实现代码:


 1 /******************************************************************

 2 函数名称:InitBufInArray()

 3 函数功能:模拟采样数据,采样数据中包含3种频率正弦波(350Hz,8400Hz,18725Hz)

 4 参数说明:

 5 备    注:在lBufInArray数组中,每个数据的高16位存储采样数据的实部,

 6           低16位存储采样数据的虚部(总是为0)

 7 作者:博客园 依旧淡然 8 *******************************************************************/

 9 void InitBufInArray()

10 {

11     unsigned short i;

12     float fx;

13     for(i=0; i14     {

15         fx = 1500 * sin(PI2 * i * 350.0 / Fs) +

16              2700 * sin(PI2 * i * 8400.0 / Fs) +

17              4000 * sin(PI2 * i * 18725.0 / Fs);

18         lBufInArray[i] = ((signed short)fx) << 16;

19     }

20 }


其中,NPT是采样点数256,PI2是2π(即6.28318530717959),Fs是采样频率44800。可以看到采样数据中包含了3种频率的正弦波,分别为350Hz,8400Hz和18725Hz。


2.4调用DSP库函数进行FFT


进行256点的FFT,只需要调用STM32DSP库函数中的cr4_fft_256_stm32()函数即可。该函数的原型为:


voidcr4_fft_256_stm32(void*pssOUT,void*pssIN,uint16_tNbin);


其中,参数pssOUT表示FFT输出数组指针,参数pssIN表示要进行FFT运算的输入数组指针,参数Nbin表示了点数。至于该函数的具体实现,因为是用汇编语言编写的,我也不懂,这里就不妄谈了。


下面是具体的调用实例:


cr4_fft_256_stm32(lBufOutArray,lBufInArray,NPT);


其中,参数lBufOutArray同样是一个long类型的数组,参数lBufInArray就是存放模拟采样数据的采样数组,NPT为采样点数256。


调用该函数之后,在lBufOutArray数组中就存放了进行FFT运算之后的结果数据。该数组中每个元素的数据格式为;高16位存储虚部,低16位存储实部。


2.5计算各次谐波幅值


得到FFT运算之后的结果数据之后,就可以计算各次谐波的幅值了。


下面是具体的实现代码:


 1 /******************************************************************

 2 函数名称:GetPowerMag()

 3 函数功能:计算各次谐波幅值

 4 参数说明:

 5 备注:先将lBufOutArray分解成实部(X)和虚部(Y),然后计算幅值(sqrt(X*X+Y*Y)

 6 作者:博客园 依旧淡然 7 *******************************************************************/

 8 void GetPowerMag()

 9 {

10     signed short lX,lY;

11     float X,Y,Mag;

12     unsigned short i;

13     for(i=0; i14     {

15         lX  = (lBufOutArray[i] << 16) >> 16;

16         lY  = (lBufOutArray[i] >> 16);

17         X = NPT * ((float)lX) / 32768;

18         Y = NPT * ((float)lY) / 32768;

19         Mag = sqrt(X * X + Y * Y) / NPT;

20         if(i == 0)

21             lBufMagArray[i] = (unsigned long)(Mag * 32768);

22         else

23             lBufMagArray[i] = (unsigned long)(Mag * 65536);

24     }

25 }


其中,数组lBufMagArray存储了各次谐波的幅值。


2.6实验结果


通过串口,我们可以将lBufMagArray数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示:


  i,         P,       Mag,         X,         Y

   0,         0,         4,         0,        -4

   1,       175,        14,        -6,        -4

   2,       350,      1492,       746,        -3

   3,       525,        11,        -5,        -3

   4,       700,         8,        -3,        -3

   5,       875,         8,        -4,        -2

   6,      1050,         6,        -3,         0

   7,      1225,         6,        -3,         0

   8,      1400,         8,        -4,        -2

   9,      1575,         8,        -4,         0

  10,      1750,         4,        -2,         0

  11,      1925,         8,        -4,        -1

  12,      2100,         6,        -3,         0

  13,      2275,         5,        -2,        -2

  14,      2450,         6,        -3,        -1

  15,      2625,         8,        -3,        -3

  16,      2800,         4,        -2,         0

  17,      2975,         6,        -3,        -1

  18,      3150,         6,        -3,         0

  19,      3325,         6,        -3,         0

  20,      3500,         2,        -1,         0

  21,      3675,         4,        -2,         0

  22,      3850,         4,        -2,         0

  23,      4025,         4,        -2,         0

  24,      4200,         6,        -3,         0

  25,      4375,         6,        -3,         0

  26,      4550,         4,        -2,         0

  27,      4725,         6,        -3,         0

  28,      4900,         2,        -1,         0

  29,      5075,         4,        -2,        -1

  30,      5250,         4,        -2,         0

  31,      5425,         2,        -1,         0

  32,      5600,         4,        -2,        -1

  33,      5775,         6,        -3,        -1

  34,      5950,         2,        -1,        -1

  35,      6125,         6,        -3,        -1

  36,      6300,         2,        -1,         0

  37,      6475,         6,        -3,         0

  38,      6650,         4,        -2,         0

  39,      6825,         4,        -2,        -1

  40,      7000,         2,        -1,         0

  41,      7175,         6,        -3,         0

  42,      7350,         2,        -1,         0

  43,      7525,         2,        -1,         0

  44,      7700,         2,        -1,         0

  45,      7875,         2,        -1,         0

推荐阅读

史海拾趣

Allianc公司的发展小趣事

Allianc公司成立于XXXX年,初创时期面临着资金短缺、市场竞争激烈等诸多挑战。公司创始人凭借对电子行业的深刻理解和敏锐的市场洞察力,带领团队开发出了一款具有创新性的电子产品,并成功获得了第一批订单。然而,随着市场的不断变化和竞争的加剧,公司必须不断创新和优化产品,才能保持竞争优势。在创始人的带领下,Allianc公司逐步稳定了市场地位,为后续发展奠定了坚实基础。

Frequency Electronics Inc公司的发展小趣事

高频电子成立于1961年(也有资料显示为1962年),最初主要根据美国政府的最终使用合同,生产专有的精密时间和频率技术产品。在20世纪90年代中期,公司敏锐地捕捉到市场变化,开始从一家国防合同制造商转变为面向商业和政府最终用途的高科技供应商。这一战略转型不仅拓宽了公司的业务范围,还为公司带来了更多的市场机遇和增长潜力。

e2v technologies公司的发展小趣事

2016年,e2v被Teledyne Technologies公司收购,成为Teledyne e2v。这一合并不仅为e2v带来了更多的资源和支持,也为其开启了新的发展篇章。Teledyne e2v在继续保持其在图像传感器领域的领先地位的同时,也积极拓展新的市场和应用领域,为电子行业的发展贡献更多的力量。

ABECO公司的发展小趣事

在电子行业发展日新月异的背景下,ABECO始终保持着对技术创新的热情。公司投入大量资源进行研发,推出了一系列具有创新性的产品,如智能剥线工具、高精度切割机等。这些产品不仅提高了生产效率,也降低了操作难度,赢得了客户的广泛好评。同时,ABECO还积极与高校和研究机构合作,引进新技术和人才,推动公司的技术创新不断向前发展。

Conflux公司的发展小趣事

Conflux公司自创立之初,便专注于区块链技术的研发与应用。在电子支付领域,公司团队成功研发出了一种高效、安全的分布式账本技术,这一技术突破迅速吸引了业界的关注。随后,Conflux与多家金融机构合作,推出了基于区块链技术的电子支付解决方案,不仅提高了交易速度,还大大降低了交易成本。这一系列的创新举措使Conflux在电子支付领域崭露头角,奠定了其在行业内的领先地位。

Goldentech Discrete Semiconductor Inc公司的发展小趣事

进入21世纪后,随着全球电子市场的竞争加剧,Goldentech意识到单靠技术创新已不足以维持其市场地位。因此,公司开始积极寻求与行业领先企业的战略合作。通过与一家知名芯片设计公司的深度合作,Goldentech成功将其高性能离散半导体器件集成到对方的芯片设计中,从而实现了产品的广泛应用。这一合作不仅扩大了Goldentech的市场份额,还提升了其品牌知名度和行业影响力。

问答坊 | AI 解惑

protel图解教程

看看吧,挺有帮助的,快速入门…

查看全部问答>

Cypress:触摸屏将成为2010年市场热点

观察琳琅满目的电子产品,我们不难发现触摸屏的采用已经越来越普及,从手机到GPS,从数码相机到刚刚上市的iPad,消费者已经不再满足于简单的点击、拉伸,触摸控制技术的发展可谓日新月异。 市场调研机构iSuppli的预测,未来几年全球触摸屏幕设备的 ...…

查看全部问答>

如何解决操作系统不能动态加载驱动程序的故障呢?

我在网吧,发现网吧的电脑上,系统不允许动态加载驱动程序,凡是有会动态加载驱动程序的比如CPU-Z、或VirtualPC2007安装程序等等都无法执行。我想请教一下到底系统是哪里被设置了,如何才能解开这些限制呢?我就是想在网吧的电脑上使用VPC2007在自 ...…

查看全部问答>

关于DSP+FPGA系统 时钟问题

    我做的一个基于DSP的系统中,DSP做主处理器,控制着整个系统,包括信号处理,整体调度等;选择了一块Xilinx的FPGA做FIFO UART和系统的逻辑控制和译码。DSP的时钟输入为15MHz,经过内部的PLL倍频为较高频率,FPGA需要25M或一下的时钟输 ...…

查看全部问答>

我见过讲Makefile最好中文文章

建议大家看一下,做些很厉害,讲的很到位很全面!~…

查看全部问答>

威视锐ZYNQ开发板-ZingSK高清视频接口实例--HDMI

1. 概述ZingSK开发套件采用核心板加底板的方式,方便用户使用自定义的低成本的底板. ZingSK配套的底板也拥有丰富的接口, ZingSK外观如图1. 图1 本实例主要介绍底板上高清多媒体接口HDMI的使用,并通过软硬件协同设计的方法来实现彩条输出.通过ZYNQ ...…

查看全部问答>

msp430 DCO外接电阻(ROSC)设置频率 无效 求助

此为TI官网例程,msp430f2618 DCO外接电阻(ROSC)设置频率,用IAR编译,430仿真器JTAG口下载仿真,单步调试到标志处(如下代码黄色背景)处程序跑飞,不能继续,实在不明白为什么,求高手知道。 (代码说明中下滑线处说这可能影响到JTAG重新建立链 ...…

查看全部问答>

单片机I/O控制电源开断

我现在想用单片机的I/O口来控制30路电源的开断(电源都是12V,1A),因为有很多路要控制,所以不想用继电器,太占板子的空间了。请问下大家有没有什么好的电路或者是方法可以推荐一下。每一路电源都是相互独立的,考虑到I/O的数量,如果能节省点I/O ...…

查看全部问答>

对于具有过流保护,自恢复功能的led电路的问题?

有8个LED灯,限流是370mA。我是把电流一下降到只有1个LED都不会过流的电压好,还是慢慢的把电压降下来好????????????…

查看全部问答>

LPC1830 SWD無法燒錄

各位,我用的LPC1830FBD144,搭ULINK-ME燒錄,KEILC提示如下,SWD Communication failure,求各位幫忙!…

查看全部问答>