STM32F4 FPU浮点运算单元

本文介绍了STM32F4系列微控制器如何启用和利用其内置的硬件浮点运算单元(FPU),通过设置CPACR寄存器和MDK编译器选项来加速浮点运算。同时,文中提到了在UCOSIII移植过程中的FPU支持问题,以及解决低版本UCOSIII不支持STM32F4 FPU的策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FPU 即浮点运算单元(Float Point Unit)。浮点运算,对于定点 CPU(没有 FPU 的 CPU)

来说必须要按照 IEEE-754 标准的算法来完成运算,是相当耗费时间的。而对于有 FPU 的 CPU

来说,浮点运算则只是几条指令的事情,速度相当快。

STM32F4 属于 Cortex M4F 架构,带有 32 位单精度硬件 FPU,支持浮点指令集,相对于

Cortex M0 和 Cortex M3 等,高出数十倍甚至上百倍的运算性能。

STM32F4 硬件上要开启 FPU 是很简单的,通过一个叫:协处理器控制寄存器(CPACR)

的寄存器设置即可开启 STM32F4 的硬件 FPU,该寄存器各位描述如图 51.1.1.1 所示:

                           图 51.1.1.1 协处理器控制寄存器(CPACR)各位描述

这里我们就是要设置 CP11 和 CP10 这 4 个位,复位后,这 4 个位的值都为 0,此时禁止访

问协处理器(禁止了硬件 FPU),我们将这 4 个位都设置为 1,即可完全访问协处理器(开启

硬件 FPU),此时便可以使用 STM32F4 内置的硬件 FPU 了。CPACR 寄存器这 4 个位的设置,

我们在 system_stm32f4xx_c 文件里面开启,代码如下:

void SystemInit(void)

{

/* FPU settings ------------------------------------------------------------*/

#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)

SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */

#endif

……//省略部分代码

}

此部分代码是系统初始化函数的部分内容,功能就是设置 CPACR 寄存器的 20~23 位为 1,

以开启 STM32F4 的硬件 FPU 功能。从程序可以看出,只要我们定义了全局宏定义标识符

__FPU_PRESENT 以及__FPU_USED 为 1,那么就可以开启硬件 FPU。其中宏定义标识符

__FPU_PRESENT 用来确定处理器是否带 FPU 功能,标识符__FPU_USED 用来确定是否开启FPU 功能。

实际上,因为 F4 是带 FPU 功能的,所以在我们的 stm32f4xx.h 头文件里面,我们默认是定

义了__FPU_PRESENT 为 1。大家可以打开文件搜索即可找到下面一行代码:

#define __FPU_PRESENT 1

但是,仅仅只是说明处理器有 FPU 是不够的,我们还需要开启 FPU 功能。开启 FPU 有两

种方法,第一种是直接在头文件 STM32f4xx.h 中定义宏定义标识符__FPU_USED 的值为 1。也

可以直接在 MDK 编译器上面设置,我们在 MDK5 编译器里面,点击

按钮,然后在 Target

选项卡里面,设置 Floating Point Hardware 为 Use Single Precision,如图 51.1.1.2 所示:

                                          图 51.1.1.2 编译器开启硬件 FPU 选型

经过这个设置,编译器会自动加入标识符__FPU_USED 为 1。这样遇到浮点运算就会使用

硬件 FPU 相关指令,执行浮点运算,从而大大减少计算时间。

最后,总结下 STM32F4 硬件 FPU 使用的要点:

1, 设置 CPACR 寄存器 bit20~23 为 1,使能硬件 FPU。

2, MDK 编译器 Code Generation 里面设置:Use FPU。

经过这两步设置,我们的编写的浮点运算代码,即可使用 STM32F4 的硬件 FPU 了,可以

大大加快浮点运算速度。

转了等于我会了~真是个小机灵鬼呢~

附:UCOSIII移植过程中,似乎是低版本的不支持FPU,在移植到STM32F4系列时,有浮点计算时任务不执行,在PendSv_Handle中,并未对浮点处理寄存器做进出栈的操作。最新的ucosIII好似更新到了V3.09版本呢,官网的Release文档也有相关FPU的更新说明,但是我依然选择在UCOSIIIde V3.0.4版本上更新,借助网络上前辈的荫,成功解锁了UCOSIII移植到STM32F4系列的FPU使用

### STM32F4 浮点运算单元 (FPU) 配置与使用 #### 启用 FPU 和 DSP 扩展功能 为了使STM32F4能够执行浮点运算,在项目初始化阶段需确保启用了硬件浮点运算支持。这涉及到修改`stm32f4xx_hal_conf.h`文件中的预处理器指令来激活必要的库特性[^1]。 ```c #define __FPU_PRESENT 1U /*!< Value is defined by CMSIS */ #define __FPU_USED 1U /*!< Set to 1 if FPU is used */ ``` 上述设置告知编译器该设备具备并打算利用内置的浮点处理能力。当这两个宏被定义为 `1` 时,意味着目标MCU确实装备有FPU,并且应用程序计划调用其资源来进行更复杂的数学计算操作。 #### 初始化过程中的注意事项 在启动代码里应当包含适当的配置步骤以正确地准备FPU环境。通常情况下,HAL库会自动完成大部分工作;然而开发者仍需要注意某些特定情况下的额外需求: - 如果采用裸机编程方式,则可能需要手动编写汇编代码片段用于开启协处理器接口。 - 对于链接脚本而言,应该指定`.fpreg`段放置位置以便保存寄存器状态信息。 #### 编写高效的浮点算法 一旦成功设置了这些选项之后就可以自由运用C/C++语言里的标准数据类型如float,double等进行开发了。值得注意的是,尽管有了专门设计过的加速引擎辅助,但在嵌入式环境中合理规划内存占用量以及优化性能依然是至关重要的考量因素之一。 对于那些对精度要求不高或者希望进一步提升效率的应用场景来说,可以考虑使用单精度(`float`)代替双精度(`double`)变量,因为前者往往能带来更好的速度表现同时减少存储空间消耗。 #### 实际应用案例分析 假设现在有一个简单的例子想要展示如何在一个基于STM32CubeMX生成的基础框架上实现基本正弦波形发生器的功能。这里的关键在于理解怎样通过调整定时器中断频率配合恰当的比例因子将角度转换成对应的幅度值输出给DAC模块形成连续变化信号。 ```c #include "main.h" void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void){ HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); /* Enable the FPU before using floating-point operations */ SCB->CPACR |= ((3UL << 10*2)|(3UL<<11*2)); //Enable CP10 and CP11 Full Access while (1){ float angle = 0; for(angle=0;angle<360;angle+=0.1){ float amplitude = sin((angle * M_PI)/180); // Convert degrees to radians then calculate sine value. uint16_t dac_value = (uint16_t)((amplitude + 1)* DAC_MAX_VALUE/2); // Scale between 0~Vref HAL_DAC_SetValue(&hdac, DAC_CHANNEL_1, DAC_ALIGN_12B_R,dac_value); HAL_Delay(1); } } } ``` 此程序展示了如何安全有效地启用FPU访问权限并通过它完成一次完整的周期性函数绘图任务。注意这里的延迟是为了模拟实际应用场景中可能会存在的采样间隔时间差异而加入的人工延时机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值