[应用相关] STM32使用ARM优化数学库arm_math.h函数库配置指南

[复制链接]
3232|16
 楼主| 我喜欢打游戏 发表于 2023-3-28 11:21 | 显示全部楼层 |阅读模式
为什么要用到这个库
这段时间在调Robomaster的电机,用的是大疆的F427主控,角度控制为了达到快速精准的效果,需要将PID的一个段写成非线性的方式,要用到"math.h"库当中的pow函数,但是使用KEIL自带的math.h对于单片机来说效率并不高,可能过多占用MCU,经了解,发现ARM提供了一个专为单片机设计的基于CM4内核的一个数学库,可以基于内核级别的数**算优化,比传统的数学库速度快十到百倍左右,于是学习了一下调用这个函数库的一些步骤。

关于这个函数库的详细信息,请移步官网:https://www.keil.com/pack/doc/CMSIS/DSP/html/arm__math_8h.html


 楼主| 我喜欢打游戏 发表于 2023-3-28 11:23 | 显示全部楼层
开始配置
废话不多说,我们先来看看存放Cortex内核核心外设使用的"core_cm4.h"文件:
  1. #if defined ( __CC_ARM )
  2.   #if defined __TARGET_FPU_VFP
  3.     #if defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)
  4.       #define __FPU_USED       1U
  5.     #else
  6.       #error "Compiler generates FPU instructions for a device without an FPU (check __FPU_PRESENT)"
  7.       #define __FPU_USED       0U
  8.     #endif
  9.   #else
  10.     #define __FPU_USED         0U
  11.   #endif
  12. //

第一个__CC_ARM,是选择KEIL作为编译器的分支,因此我们需要在工程宏定义中添加__CC_ARM的宏定义。然后__TARGET_FPU_VFP也是必须要添加到宏定义中的。

再来说说__FPU_PRESENT和__FPU_USED这两个宏定义的作用吧,__FPU_PRESENT在编译时,编译系统用于判断该设备是否拥有FPU运算功能,也就是说,它作为编译是否加入FPU的总开关,因此我们需要加入这个宏,并且将它设为1。

但是仔细看看,stm32f427xx.h文件中已经有了这个宏定义,表示stm32f427系列是支持FPU功能的:
  1. #define __CM4_REV                 0x0001U  /*!< Core revision r0p1                            */
  2. #define __MPU_PRESENT             1U       /*!< STM32F4XX provides an MPU                     */
  3. #define __NVIC_PRIO_BITS          4U       /*!< STM32F4XX uses 4 Bits for the Priority Levels */
  4. #define __Vendor_SysTickConfig    0U       /*!< Set to 1 if different SysTick Config is used  */
  5. #define __FPU_PRESENT             1U       /*!< FPU present                                //需要注释掉

但是编辑器显示core_cm4.h直接跳到#else里面了,也就是说编译器执行到这里不认为已经定义了__FPU_PRESENT,这是由于内核文件并不会包含中间驱动的宏定义的,所以我们需要在全局添加宏定义并且赋值为1:__FPU_PRESENT=1,然后编译时编译器会报错,因为重复定义了__FPU_PRESENT,所以我们把stm32f427xx.h中的__FPU_PRESENT注释掉:
  1. //#define __FPU_PRESENT             1U       /*!< FPU present

这样就不会编译报错了,这样,内核编译时就会定义启动内核的FPU支持:
  1. #define __FPU_USED       1U

这样,编译部分的修改就已经完成了。之后就是添加头文件路径和源文件路径,这里就只需要添加一个头文件路径即可,整个函数库共用这几个头文件。
9018764225d7c7d9a9.png
7553164225d87eeb62.png
接下来添加需要的源文件,至于源文件需要哪些,就要看自己的需要了,一共有下面着这一些文件夹,把自己需要的加入工程即可,全部加进来编译时间翻倍,不建议全部添加,具体的函数功能打开源文件有英文描述,非常的清晰。

7709064225d97aaf12.png
3123464225da26e45c.png
全部工作做好后,就可以编译了,然后会发现编译仍然报错,提示未定义的宏,到错误处,发现arm_math.h文件中有这么一段宏判断:
  1. #if defined(ARM_MATH_CM7)
  2.   #include "core_cm7.h"
  3.   #define ARM_MATH_DSP
  4. #elif defined (ARM_MATH_CM4)
  5.   #include "core_cm4.h"
  6.   #define ARM_MATH_DSP
  7. #elif defined (ARM_MATH_CM3)
  8.   #include "core_cm3.h"
  9. #elif defined (ARM_MATH_CM0)
  10.   #include "core_cm0.h"
  11.   #define ARM_MATH_CM0_FAMILY
  12. #elif defined (ARM_MATH_CM0PLUS)
  13.   #include "core_cm0plus.h"
  14.   #define ARM_MATH_CM0_FAMILY
  15. #elif defined (ARM_MATH_ARMV8MBL)
  16.   #include "core_armv8mbl.h"
  17.   #define ARM_MATH_CM0_FAMILY
  18. #elif defined (ARM_MATH_ARMV8MML)
  19.   #include "core_armv8mml.h"
  20.   #if (defined (__DSP_PRESENT) && (__DSP_PRESENT == 1))
  21.     #define ARM_MATH_DSP
  22.   #endif
  23. #else
  24.   #error "Define according the used Cortex core ARM_MATH_CM7, ARM_MATH_CM4, ARM_MATH_CM3, ARM_MATH_CM0PLUS, ARM_MATH_CM0, ARM_MATH_ARMV8MBL, ARM_MATH_ARMV8MML"
  25. #endif

而ARM_MATH_DMP又是作为arm_math库的开关,所以我们需要全局宏定义ARM_MATH_CM4来开启。

最后,引入"arm_math.h"头文件,然后再编译,通过。然后就可以使用自己添加进工程的arm版本的math函数了。
 楼主| 我喜欢打游戏 发表于 2023-3-28 11:24 | 显示全部楼层
总结
经过前面的探索,我总结一下配置的步骤:

添加全局宏:USE_HAL_DRIVER,STM32F427xx,__CC_ARM,__TARGET_FPU_VFP,__FPU_PRESENT,ARM_MATH_CM4

注释或者删除stm32f427xx.h中关于的__FPU_PRESENT定义

添加头文件路径

添加工程需要的math源文件,ARM已经帮我们按文件夹分好类了

在工程中引入头文件#include “arm_math.h”

开始使用库中的函数
Clyde011 发表于 2024-1-27 09:16 | 显示全部楼层

整流器或功率开关管与每个电容端的连线长度和宽度都要一样
万图 发表于 2024-1-27 11:12 | 显示全部楼层

交流电流环路的布线要在其他引线之前布好
Uriah 发表于 2024-1-27 12:15 | 显示全部楼层

其他的信号和地要与这些高压引线和它的散热部分隔开
Uriah 发表于 2024-1-27 12:15 | 显示全部楼层

其他的信号和地要与这些高压引线和它的散热部分隔开
您需要登录后才可以回帖 登录 | 注册

本版积分规则

80

主题

626

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部