专家
公告
财富商城
电子网
旗下网站
首页
问题库
专栏
标签库
话题
专家
NEW
门户
发布
提问题
发文章
DSP
如何使用STM32提供的DSP库进行FFT
2019-07-13 10:11
发布
生成海报
站内文章
/
DSP
17698
0
940
原文:http://www.cnblogs.com/menlsh/p/4154070.html
前些日子,因为需要在
STM32F103
系列处理器上,对采集的音频信号进行
FFT
,所以花了一些时间来研究如何高效并精确的在
STM32F103
系列处理器上实现
FFT
。在网上找了很多这方面的资料做实验并进行比较,最终选择了使用
STM32
提供的
DSP
库这种方法。
本文将以一个实例来介绍如何使用
STM32
提供的
DSP
库函数进行
FFT
。
1.FFT
运算效率
使用
STM32
官方提供的
DSP
库进行
FFT
,虽然在使用上有些不灵活(因为它是基
4
的
FFT
,所以
FFT
的点数必须是
4^n
),但其执行效率确实非常高效,看图
1
所示的
FFT
运算效率测试数据便可见一斑。该数据来自
STM32 DSP
库使用文档。
图
1 FFT
运算效率测试数据
由图
1
可见,在
STM32F10x
系列处理器上,如果使用
72M
的系统主频,进行
64
点的
FFT
运算,仅仅需要
0.078ms
而已。如果是进行
1024
点的
FFT
运算,也才需要
2.138ms
。
2.
如何使用
STM32
提供的
DSP
库函数
2.1
下载
STM32
的
DSP
库
大家可以从网上搜索下载得到
STM32
的
DSP
库,这里提供一个下载的地址:
https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/DispForm.aspx?ID=30831&RootFolder=%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex%5fmx%5fstm32%2fSTM32F10x%20DSP%20library%2c%20where%20is%20it
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 项目框架
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
作 者:博客园 依旧淡然(
http://www.cnblogs.com/menlsh/
)
8
******************************************************************
*/
9
void
InitBufInArray()
10
{
11
unsigned
short
i;
12
float
fx;
13
for
(i=
0
; i
)
14
{
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
,只需要调用
STM32 DSP
库函数中的
cr4_fft_256_stm32()
函数即可。该函数的原型为:
void cr4_fft_256_stm32(void *pssOUT, void *pssIN, uint16_t Nbin);
其中,参数
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
作 者:博客园 依旧淡然(
http://www.cnblogs.com/menlsh/
)
7
******************************************************************
*/
8
void
GetPowerMag()
9
{
10
signed
short
lX,lY;
11
float
X,Y,Mag;
12
unsigned
short
i;
13
for
(i=
0
; i
2; i++
)
14
{
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
数组中各次谐波的幅值(即各个频率分量的幅值)输出打印出来,具体实验数据如下所示:
View Code
在以上的实验数据中,我们分别打印出来了点数、频率、幅值、实部、虚部信息。
由以上的实验数据,我们可以看出,在频率为
350Hz
,
8400Hz
和
18725Hz
时,幅值出现峰值,分别为
1492
、
2696
和
3996
,这与我们所预期的结果正好相符,从而验证了实验结果的正确性。
Ta的文章
更多
>>
做DSP最应该懂得57个问题
0 个评论
如何使用STM32提供的DSP库进行FFT
0 个评论
热门文章
×
关闭
举报内容
检举类型
检举内容
检举用户
检举原因
广告推广
恶意灌水
回答内容与提问无关
抄袭答案
其他
检举说明(必填)
提交
关闭
×
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮