如何使用STM32F4的DSP库
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用STM32F4的DSP库相关的知识,希望对你有一定的参考价值。
参考技术A 我们平常所使用的CPU为定点CPU,意思是进行整点数值运算的CPU。当遇到形如1.1+1.1的浮点数
运算时,定点CPU就遇到大难题了。对于32位单片机,利用Q化处理能发挥他本身的性能,但是精度和速度仍然不会提高很多。
现在设计出了一个新的CPU,叫做FPU,这个芯片专门处理浮点数的运算,这样处理器就将整点数和浮点数分开来处理,整点数交由定点CPU处理而浮点数交由FPU处理。我们见到过TI的DSP,还有
STM32F4
系列的带有DSP功能的
微控制器
。前者笔者没有用过,不作评论,而后者如果需要用到FPU的
浮点运算
功能,必须要进行一些必要的设置。
首先,由于浮点运算在FPU中进行,所以首先应该
使能
FPU运行。在system_init()中,定义__FPU_PRESENT和__FPU_USED
/*
FPU
settings
------
------------------------------------------------------*/
#if
(__FPU_PRESENT
==
1)&&
(__FPU_USED
==
1)
SCB->CPACR
|=
((3UL<<
10*2)|(3UL
<<
11*2));
/*set
CP10
and
CP11
Full
Access
*/
#endif
这样就使能了FPU。
对于上述改变,当程序中出现这种简单的
加减乘除运算
FPU就起作用了。但是对于复杂的如三角运算、
开方
运算等,我们就需要加入math.h
头文件
。但是如果单纯的加入他,那么Keil会自动调用内部的math.h,该头文件是针对
ARM处理器
的,专门用于定点CPU和标准算法(IEEE-754)。对于使用了FPU的STM32F4是没有任何作用的。所以,需要将math.h换成ST的库,即arm_math.h。在该头文件中,涉及到另一个文件core_cmx.h(x=0、3、4),当然了,如同STM32F1系列一样,在工程中加入core_cm4.h即可。
到这里,算是全部设置完毕,之差最后一步,调用!但是别小看了这一步,因为如果调用的不正确,全面的设置就白费了。在使用
三角函数
如sin()、cos()时不要直接写如上形式,因为他们函数的名字来自于math.h,所以你调用的仍旧是Keil库中的标准math.h。要使用arm_math.h中的arm_sin_f32()函数(见Line.5780,
原函数
见DSP_Lib\Source\FastMathFunctions),可以看到他利用的是
三次样条插值法
快速
求值
(见Line.263
/*
Cubic
interpolation
process
*/)。
注意一下例外函数,sqrt(),在arm_math.h中为arm_sqrt_f32()。使用他的时候需要同时开启#if(__FPU_USED
==
1)
&&
defined
(
__CC_ARM
)才行,切记!还可以发现开方函数还有q15和q31之分,我想他们的区别就是精度的问题,但是他们没有应用FPU来计算,说白了就是利用0x5f3759df这个数进行快速开方,大家如果对这个数很陌生,查阅
http://en.wikipedia.org/wiki/Fast_inverse_square_root
。不过他的处理可能有些不同。
STM32F4使用FPU+DSP库进行FFT运算的测试过程
测试环境:单片机:STM32F407ZGT6 IDE:Keil5.20.0.0 固件库版本:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0
第一部分:使用源码文件的方式,使用void arm_cfft_radix4_f32(const arm_cfft_radix4_instance_f32 * S,float32_t * pSrc)函数进行FFT运算。
准备空工程,配置Keil环境.使能STM32F4的FPU单元。
开启硬件浮点运算,等效于在C/C++->define中定义__FPU_USED,__FPU_PRESENT两个宏
添加全局宏定义,使能DSP库所有的功能
图中STM32F4XX,USE_STDPERIPH_DRIVER是新建工程都会用到的配置宏,新建工程参考:http://blog.csdn.net/qianrushi_jinxifeng/article/details/19673755
其他宏ARM_MATH_CM4,__CC_ARM,ARM_MATH_MATRIX_CHECK,ARM_MATH_ROUNDING 请参考:http://blog.csdn.net/desert187/article/details/20527921
向工程中添加使用到的DSP库源码
在stm32f4_dsp_stdperiph_lib\\STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\\Libraries\\CMSIS\\DSP_Lib\\Source目录下会有如下目录,都是DSP函数库
BasicMathFunctions 基本数学函数:提供浮点数的各种基本运算函数,如向量加减乘除等运算。 CommonTables arm_common_tables.c文件提供位翻转或相关参数表。 ComplexMathFunctions 复杂数学功能,如向量处理,求模运算的。 ControllerFunctions 控制功能函数。包括正弦余弦,PID电机控制,矢量Clarke变换,矢量Clarke逆变换等。 FastMathFunctions 快速数学功能函数。提供了一种快速的近似正弦,余弦和平方根等相比CMSIS计算库要快的数学函数。 FilteringFunctions 滤波函数功能,主要为FIR和LMS(最小均方根)等滤波函数。 MatrixFunctions 矩阵处理函数。包括矩阵加法、矩阵初始化、矩阵反、矩阵乘法、矩阵规模、矩阵减法、矩阵转置等函数。 StatisticsFunctions 统计功能函数。如求平均值、最大值、最小值、计算均方根RMS、计算方差/标准差等。 SupportFunctions 支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。 TransformFunctions 变换功能。包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT(RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。
我们需要CommonTables和TransformFunctions的下的部分文件
添加到工程如图
另外我们需要包含相应的头文件路径,所需的头文件在STM32F4xx_DSP_StdPeriph_Lib_V1.4.0\\Libraries\\CMSIS\\Include路径下可以找到
编写main()函数,
1 #include "stm32f4xx_conf.h" 2 //位带操作 3 #include "sys.h" 4 #include "delay.h" 5 #include "usart.h" 6 //LCD显示屏功能 7 #include "Nick_lcd.h" 8 #include "Nick_keys.h" 9 10 #include "arm_math.h" 11 #define FFT_LENGTH 1024 //FFT长度,默认是1024点FFT 12 13 float fft_inputbuf[FFT_LENGTH*2]; //FFT输入输出数组,此数组为arm_cfft_radix4_f32的输入输出数组,前一个元素为实部,后一个为虚部,每两个元素代表一个点. 14 float fft_outputbuf[FFT_LENGTH]; //arm_cmplx_mag_f32() 幅度输出数组 15 arm_cfft_radix4_instance_f32 scfft; 16 17 int main(void) 18 { 19 delay_init(168); 20 lcd_init(0); //初始化LCD 21 key_init(); 22 uart_init(115200); //初始化串口波特率为115200 23 24 arm_cfft_radix4_init_f32(&scfft,FFT_LENGTH,0,1);//初始化scfft结构体,设定FFT相关参数 25 26 while(1) 27 { 28 u32 keyval = (u32)keys_scan(0); 29 if(keyval==1) 30 { 31 for(int i=0;i<FFT_LENGTH;i++)//生成信号序列 32 { 33 fft_inputbuf[2*i]=15 + 10*arm_sin_f32(2*PI*i*100/FFT_LENGTH) + \\ 34 5.5*arm_sin_f32(2*PI*i*150/FFT_LENGTH); //生成实部 35 36 fft_inputbuf[2*i+1]=0;//虚部全部为0 37 } 38 arm_cfft_radix4_f32(&scfft,fft_inputbuf); //FFT计算(基4) 39 arm_cmplx_mag_f32(fft_inputbuf,fft_outputbuf,FFT_LENGTH); //把运算结果复数求模得幅值 40 41 printf("FFT Result:\\r\\n"); 42 for(int i=0;i<FFT_LENGTH;i++) 43 { 44 printf("%f\\r\\n",fft_outputbuf[i]); 45 } 46 } 47 delay_ms(60); 48 } 49 }
代码分析:如代码所示,利用arm_sin_f32函数产生了,一个基波幅度为15,频率100Hz是幅度为10,频率150Hz是幅度为5.5的信号。
经过FFT运算后,用arm_cmplx_mag_f32()函数求出赋值,并通过串口打印出来。
编译运行
结果分析:
对串口收到的数据用matlab绘图,如下
如图,基波幅度为:15360/1024 = 15
100Hz成分幅度为: 5120*2/1024 = 10
150Hz成分幅度为: 2816*2/1024 = 5.5
因此所得的结果是正确的。博主目前为测试相位,故在此不做说明。
后记,这是使用源码的方式进行操作的,所有源码可跳转,可编辑。但添加麻烦。
下一篇将使用ST提供的.lib库直接进行运算。链接:http://www.cnblogs.com/NickQ/p/8541156.html
以上是关于如何使用STM32F4的DSP库的主要内容,如果未能解决你的问题,请参考以下文章
STM32F4基于库函数移植DSP源码“DSP简介及工程创建“
STM32F4基于库函数移植DSP源码“DSP简介及工程创建“