浮点运算一直是定点CPU的难题,比如一个简单的1.1+1.1,定点CPU必须要按照IEEE-754标准的算法来完成运算,效率低下。虽然对32为单片机来说,将浮点数进行Q化处理能充分发挥32位单片机的运算性能,但是精度会受到限制。而对于有FPU(浮点运算单元)的单片机来说,浮点加法只是几条指令的事情。
STM32F4xx属于Cortex M4F架构,这和M0、M3的最大不同就是多了一个F-float。带有32位的单精度硬件FPU,支持浮点指令集,相对比M0和M3架构,浮点运算性能高出数十倍甚至上百倍。
1:STM32F4xx FPU功能的开启
第一步:
在stm32f4xx.h中定义宏__FPU_PRESENT ; __FPU_USED
#define __CM4_REV 0x0001 /*!< Core revision r0p1 */
#define __MPU_PRESENT 1 /*!< STM32F4XX provides an MPU */
#define __NVIC_PRIO_BITS 4 /*!< STM32F4XX uses 4 Bits for the Priority Levels */
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
#define __FPU_PRESENT 1 /*!< FPU present */
#define __FPU_USED 1
第二步:
在system_stm32f4xx.c的SystemInit()中添加如下代码:
/* FPU settings ------------------------------------------------------------*/
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
第三步:
如果使用的keil是5.0以上的版本,再在keil的设置开启下FPU,如下图
这样就设置好了,CPU也就能正确高效的使用FPU进行浮点的加减乘除了。
还要特别注意,当运算中有浮点的数字时要把,数字后面加上一个f。例如表达式中有4.321参与运算。。当你不在4.321后加f时,stm32F4XX的片子不知道把他当做单精度float用FPU来运算,,默认可能是当做double来运算(我不确定),运算速度还是很慢。。 切记所有浮点数字后面加上f,,,,有时候keil会提示warning: #1035-D: single-precision operand implicitly converted to double-precision 这句话的意思就是单精度运算隐式转换成了双精度运算了。
但这还远远不够。对于复杂运算,比如三角函数,开方等运算,如果编程时还是使用math.h头文件,那是没法提升效率的,因为math.h头文件是针对所有ARM处理器的,其运算函数都是基于定点CPU和标准算法(IEEE-754),并没有预见使用FPU的情况。因此要充分发挥M4F的浮点功能,就需要使用固件库自带的arm_math.h。
第四步:
在stm32f4xx.h中增加头文件arm_math.h,并且在keil的设置中添加宏定义ARM_MATH_CM4, __CC_ARM。
在arm_math的开头部分是有这些编译控制信息:
#ifndef _ARM_MATH_H
#define _ARM_MATH_H
#define __CMSIS_GENERIC
#if defined (ARM_MATH_CM4)
#include "core_cm4.h"
#elif defined (ARM_MATH_CM3)
#include "core_cm3.h"
#elif defined (ARM_MATH_CM0)
#include "core_cm0.h"
#else
#include "ARMCM4.h"
#warning "Define either ARM_MATH_CM4 OR ARM_MATH_CM3...By Default building on ARM_MATH_CM4....."
#endif
#undef __CMSIS_GENERIC
#include "string.h"
#include "math.h"
这里因为是用的STM32F4,所以应该要ARM_MATH_CM4控制,即加入core_cm4.h因此需要在工程选项之C/C++选项卡的define中继续加入语句ARM_MATH_CM4。
加入上述编译控制项之后,高级数学函数的使用基本没问题了,比如正余弦三角函数的计算。但需要注意,如果你直接使用sin()、cos()、sqrt()这样的函数,那结果还是调用keil的math.h,因此这时要完成三角函数的计算就要使用arm_sin_f32()或者arm_cos_f32(),用法不变,这两个函数的原型在STM32F4的DSP库中。
2、DSP库的使用
STM32F4的Cortex-M4F内核不仅内置硬件FPU单元,还支持多种DSP指令集,比如支持单周期乘加指令(MAC)等。因此Cortex-M4执行所有的DSP指令集都可以在单周期内完成,而Cortex-M3和M0需要多个指令和多个周期才能完成同样的功能。比如开方运算,M3和M0只能通过迭代法(标准数学函数库)计算,而M4F直接调用VSQRT指令完成。
(1) DSP库简介
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(离散余弦变换)和配套的初始化函数。
ST不仅提供了上面所有功能函数的源码,还提供了.lib格式的文件,方便使用这些库。这些.lib文件就是由Source文件夹下的源码编译生成的。如果想看某个函数的源码,可以在Source文件夹下面查找。.lib格式文件路径:STM32F4xx_DSP_StdPeriph_Lib_V1.4.0→Libraries→CMSIS→Lib→ARM,总共有8个.lib文件,和M4F相关的有两个:
arm_cortexM4bf_math.lib(浮点Cortex-M4大端模式)
arm_cortexM4lf_math.lib(浮点Cortex-M4小端模式)
STM32F4的内核CortexM4F采用小端模式,所以选择:arm_cortexM4lf_math.lib(浮点Cortex-M4小端模式)。
(2) DSP库编程环境搭建
在设置使用DSP库之前首先要先开启硬件FPU,然后将arm_cortexM4lf_math.lib库 添加到
工程中就可以。最后,为了能够使用DSP库的所有功能,还需要添加以下几个全局宏定义:
1、__FPU_USED
2、__FPU_PRESENT
3、ARM_MATH_CM4
4、__CC_ARM(和开平方根有关)
5、ARM_MATH_MATRIX_CHECK
6、ARM_MATH_ROUNDING
stm32F4 FPU运算测试:https://download.csdn.net/download/wanrenqi/35352026
转载:https://blog.csdn.net/electrocrazy/article/details/73456697
https://blog.csdn.net/u012308586/article/details/95593163
转载:使用 stm32cubemx 生成代码,然后使能硬件fpu 和使用dsp库