当前位置:文档之家› 浮点运算

浮点运算

STM32-F4属于Cortex-M4构架,与M0、M3的最大不同就是有硬件浮点运算FPU,数学计算速度相比普通cpu运算快上几十倍。

想要使用FPU首先包含#include “arm_math.h”,还有在keil的target选项中勾选use single precision。

1.1 简单的FPU运算性能测试测试条件是开启一个100ms定时器,定时串口打印计算次数,优化级别是0,main函数中运行的代码如下:float a=1.1,b=1.2,c=1.3,d=1.4;1、FPU运算474566次,CPU运算64688次,除法速度快了7.3倍多。

c = b / d;2、FPU运算722169次,CPU运算244271次,乘法运算快了3倍。

FPU的乘法运算比除法运算快1.5倍。

c = b * d;3、FPU运算19398次,CPU运算19628次,FPU的双精度除法运算没有优势,比单精度运算慢了24.5倍c = b / 1.4;4、FPU运算503321次,CPU运算65450次,单精度常数和变量的运算差不多,单精度常数的除法快6%左右,这根编译器的关系比较大。

c = b / 1.4f;5、FPU运算519073次,跟下面比较说明整形常数和单精度常数的除法运算速度几乎一样。

c = b / 3;6、FPU运算519057次c = b / 3.0f;7、FPU运算263643次c = arm_cos_f32(1.3f);8、FPU运算3949次,说明IT给的DSP库运算速度还是很给力的,速度快了67倍c = cos(1.3f);1.2 代码设置旧版本的keil设置如下,但是发现我使用的keil5包含的新固件库已经不需要这一步了。

如果没有启动FPU而使用数学函数运算时,CPU执行时认为遇到非法指令而跳转到HardFault_Handler()中断函数中死循环。

因此,需要在系统初始化时开启FPU。

在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当__FPU_PRESENT=1且__FPU_USED=1时,编译时就加入了启动FPU的代码,CPU也就能正确高效的使用FPU进行简单的加减乘除。

需要使用固件库自带的arm_math.h而非编译器自带的math.h,这个文件根据编译控制项(__FPU_USED ==1)来决定是使用哪一种函数方法:如果没有使用FPU,那就调用keil的标准math.h头文件中定义的函数;如果使用了FPU,那就是用固件库自带的优化函数来解决问题。

1.3编译控制在arm_math.h开头部分有一些编译控制信息:[cpp] view plain copy#ifndef _ARM_MATH_H#define _ARM_MATH_H#define __CMSIS_GENERIC /* disable NVIC and Systick functions */#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 /* enable NVIC and Systick functions */#include "string.h"#include "math.h"从中可以看出,为了使用STM32F4的arm_math.h,我们需要定义ARM_MATH_CM4;否则如果不使用CMSIS的库,就会调用Keil自带的math.h。

另外,定义控制项__CC_ARM在某些数学函数中会使用VSQRT指令(浮点运算指令),运算速度比Q指令要快很多。

总结一下,需要添加宏定义ARM_MATH_CM4, __CC_ARM。

1.4添加库根据使用的器件和运算模式,添加arm_cortexMxx_math.lib到工程文件中,位于\Libraries\CMSIS\Lib\ARM中。

* The library installer contains prebuilt versions of the libraries in the <code>Lib</code> folder.* - arm_cortexM4lf_math.lib (Little endian and Floating Point Unit on Cortex-M4)* - arm_cortexM4bf_math.lib (Big endian and Floating Point Unit on Cortex-M4)* - arm_cortexM4l_math.lib (Little endian on Cortex-M4)* - arm_cortexM4b_math.lib (Big endian on Cortex-M4)* - arm_cortexM3l_math.lib (Little endian on Cortex-M3)* - arm_cortexM3b_math.lib (Big endian on Cortex-M3)* - arm_cortexM0l_math.lib (Little endian on Cortex-M0)* - arm_cortexM0b_math.lib (Big endian on Cortex-M3)注:如果存储空间不允许,也可以不添加库,只添加\Libraries\CMSIS\DSP_Lib\Source中需要的源文件和arm_math.h。

其他DSP使用示例见\Libraries\CMSIS\DSP_Lib\Examples。

1.5 DSP_Lib的文件结构BasicMathFunctions:提供浮点数的各种基本运算函数,如加减乘除等运算。

对于M0/M3只能用Q运算,即文件夹下以_q7、_q15和_q31结尾的文件;而M4F能直接硬件浮点计算,属于文件夹下以_f32结尾的文件。

CommonTables:arm_common_tables.c文件提供位翻转或相关参数表。

ComplexMathFunctions:复述数学功能,如向量处理,求模运算的。

ControllerFunctions:控制功能,主要为PID控制函数。

arm_sin_cos_f32/-q31.c函数提供360点正余弦函数表和任意角度的正余弦函数值计算功能。

FastMathFunctions:快速数学功能函数,提供256点正余弦函数表和任意任意角度的正余弦函数值计算功能,和Q值开平方运算:FilteringFunctions:滤波函数功能,主要为FIR和LMS(最小均方根)滤波函数。

MatrixFunctions:矩阵处理函数。

StatisticsFunctions:统计功能函数,如求平均值、计算RMS、计算方差/标准差等。

SupportFunctions:支持功能函数,如数据拷贝,Q格式和浮点格式相互转换,Q任意格式相互转换。

TransformFunctions:变换功能。

包括复数FFT(CFFT)/复数FFT逆运算(CIFFT)、实数FFT (RFFT)/实数FFT逆运算(RIFFT)、和DCT(离散余弦变换)和配套的初始化函数。

1.6常用库函数需要包含头文件:#include <arm_math.h>float32_t arm_sin_f32(float32_t x);float32_t arm_cos_f32(float32_t x);static __INLINE arm_status arm_sqrt_f32(float32_t in, float32_t *pOut)使用STM32F4XX自带数学库"arm_math.h"分类:STM32| 标签:STM32 arm_math DSP2013-08-28 16:24 阅读(12285)评论(0)使用STM32F4XX自带数学库"arm_math.h"STM32-F4属于Cortex-M4F构架,这与M0、M3的最大不同就是具有FPU(浮点运算单元),支持浮点指令集,因此在处理数学运算时能比M0/M3高出数十倍甚至上百倍的性能,但是要充分发挥FPU的数学性能,除了#include “arm_math.h”(而非用编译器自带的math.h)以外,(arm_math.h位于\Libraries\CMSIS\Include文件夹)还需要进行设置。

1、代码设置如果没有启动FPU而使用数学函数运算时,CPU执行时认为遇到非法指令而跳转到Hard Fault_Handler()中断函数中死循环。

因此,需要在系统初始化时开启FPU。

在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 F ull Access */#endif2、编译控制从上面的代码可以看出,当__FPU_PRESENT=1且__FPU_USED=1时,编译时就加入了启动FPU的代码,CPU也就能正确高效的使用FPU进行简单的加减乘除了。

相关主题