浮點運算一直是定點cpu的難題,比如乙個簡單的1.1+1.1,定點cpu必須要按照ieee-754標準的演算法來完成運算,對於8位微控制器來說已經完全是噩夢,對32為微控制器來說也不會有多大改善。雖然將浮點數進行q化處理能充分發揮32位微控制器的運算效能,但是精度受到限制而不會太高。對於有fpu(浮點運算單元)的微控制器或者cpu來說,浮點加法只是幾條指令的事情。
現在又fpu或者硬體浮點運算能力的主要有高階dsp(比如ti f28335/c6000/dm6xx/omap等),通用cpu(x87數學協處理器)和高階的arm+dsp處理器等。
stm32-f4屬於cortex-m4f構架,這和m0、m3的最大不同就是多了乙個f-float,即支援浮點指令集,因此在處理數**算時能比m0/m3高出數十倍甚至上百倍的效能,但是要充分發揮fpu的數學效能,還需要一些小小的設定:
1.編譯控制選項:雖然stm32f4xx韌體庫的例程之system_stm32f4***.c檔案中新增了對應的**,但給使用者評估使用的stm32f4-discovery例程中卻沒有,因此mdk4.23編寫浮點運算程式時,雖然編譯器正確產生了v指令來進行浮點運算,但是因為system_stm32f4***.c檔案沒有啟用fpu,因此cpu執行時只認為是遇到非法指令而跳轉到hardfault_handler()中斷中原地踏步。因此要保證這個錯誤不發生,必須要在system_init()函式裡面新增如下**:
#if (__fpu_present == 1) && (__fpu_used == 1)
scb->cpacr |= ((3ul << 10*2)|(3ul << 11*2));
#endif
因為這個選項是有條件編譯控制的,因此需要在工程選項(project->options for target "***x")中的c/c++選項卡的define中加入如下的語句:__fpu_present=1,__fpu_used =1。這樣編譯時就加入了啟動fpu的**,cpu也就能正確高效的使用fpu進行簡單的加減乘除了。
但這還遠遠不夠。對於複雜運算,比如三角函式,開方等運算,如果程式設計時還是使用math.h標頭檔案,那是沒法提公升效率的:因為math.h標頭檔案是針對所有arm處理器的,其運算函式都是基於定點cpu和標準演算法(ieee-754),並沒有預見使用fpu的情況,需要很多指令和複雜的過程才能完成運算,也就增加了運算時間。因此要充分發揮m4f的浮點功能,就需要使用韌體庫自帶的arm_math.h,這個檔案根據編譯控制項(__fpu_used == 1)來決定是使用那一種函式方法:如果沒有使用fpu,那就呼叫keil的標準math.h標頭檔案中定義的函式;如果使用了fpu,那就是用韌體庫自帶的優化函式來解決問題。
在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"
就是說如果不使用cmsis的,就會呼叫keil自帶的標準庫函式。否則就用cmsis的定義。這裡因為是用的stm32f4,所以應該要arm_math_cm4控制,即加入core_cm4.h,否則就用使用armcm4.h——但在編譯時keil會提示找不到這檔案。因此需要在工程選項之c/c++選項卡的define中繼續加入語句arm_math_cm4。
加入上述編譯控制項之後,高階數學函式的使用基本沒問題了,比如正余弦三角函式的計算。但需要注意,如果你直接使用sin()、cos()、sqrt()這樣的函式,那結果還算呼叫keil的math.h,你可以在debug時看對應的**,其彙編指令為bl.w __hardfp_***。因此這時要完成三角函式的計算就要使用arm_sin_f32()或者arm_cos_f32(),用法不變,這兩個函式的原型分別在arm_sin_f32.c和arm_cos_f32.c中。通過對256點三角函式表的查詢和插值演算法得到任意角度的精確函式值,這就比「原裝」的sin()、cos()快多了。
當然有些例外的是開發函式sqrt(),在arm_math.h中是這麼定義的:
static __inline arm_status arm_sqrt_f32(float32_t in, float32_t *pout)
{if(in > 0)
{// #if __fpu_used
#if (__fpu_used == 1) && defined ( __cc_arm )
*pout = __sqrtf(in);
#else
STM32F4之FPU效能的充分發揮 設定要點
浮點運算一直是定點cpu的難題,比如乙個簡單的1.1 1.1,定點cpu必須要按照ieee 754標準的演算法來完成運算,對於8位微控制器來說已經完全是噩夢,對32為微控制器來說也不會有多大改善。雖然將浮點數進行q化處理能充分發揮32位微控制器的運算效能,但是精度受到限制而不會太高。對於有fpu 浮...
KEIL中STM32F4系列使能FPU
操作步驟 1 在keil使能fpu,參考下圖 2 在keil新增fpu的巨集定義 3 一些配置巨集說明 target fpu vfp fpu的條件編譯配置巨集 開和關 配置該巨集,則開 arm math matrix check 庫函式引數檢查配置巨集 開和關 arm math rounding 庫...
STM32F4外設配置速查 FPU與DSP部分
詳細內容參考cortex m4核心程式設計手冊 stm32f4xx及更高配置stm32微控制器才有fpu支援 stm32f4帶有32位單精度硬體fpu,支援浮點指令集,整個fpu單元能被使能和關閉 使用協處理器控制暫存器 scb cpacr 中的cp11和cp10啟用 關閉fpu 晶元復位後,cp1...