1)实验平台:正点原子水星 STM32F4/F7 开发板

2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号,获取更多资料:正点原子

3)全套实验源码+手册+视频下载地址:http://www.openedv.com/thread-13912-1-1.html

第五十章 FPU 测试(Julia 分形)实验

本章,我们将向大家介绍如何开启 STM32F767 的硬件 FPU,并对比使用硬件 FPU 和不使

用硬件 FPU 的速度差别,以体现硬件 FPU 的优势。本章分为如下几个部:

50.1 FPU&Julia 分形简介

50.2 硬件设计

50.3 软件设计

50.4 下载验证

50.1 FPU&Julia 分形简介

本节将分别介绍 STM32F767 的 FPU 和 Julia 分形。

50.1.1 FPU 简介

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

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

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

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

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

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

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

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

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

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

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

我们在 system_stm32f7xx_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,

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

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

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

FPU 功能。

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

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

#define __FPU_PRESENT 1

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

有两种方法,第一种是直接在头文件 STM32f767xx.h 中定义宏定义标识符__FPU_USED 的值为

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

按钮,然后在 Target

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

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

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

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

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

1, 设置 CPACR 寄存器 bit20~23 为 1,使能硬件 FPU(参考 SystemInit 函数开头部分)。

2, MDK编译器Target选项卡中 Floating Point Hardware选项设置为:Use Double Precision。

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

大大加快浮点运算速度。

50.1.2 Julia 分形简介

Julia 分形即 Julia 集,它最早由法国数学家 Gaston Julia 发现,因此命名为 Julia(朱利亚)

集。Julia 集合的生成算法非常简单:对于复平面的每个点,我们计算一个定义序列的发散速度。

该序列的 Julia 集计算公式为:

zn+1 = zn2 + c

针对复平面的每个 x + i.y 点,我们用 c = cx + i.cy 计算该序列:

xn+1 + i.yn+1 = xn2 - yn2 + 2.i.xn.yn + cx + i.cy

xn+1 = xn2 - yn2 + cx 且 yn+1 = 2.xn.yn + cy

一旦计算出的复值超出给定圆的范围(数值大小大于圆半径),序列便会发散,达到此限

值时完成的迭代次数与该点相关。随后将该值转换为颜色,以图形方式显示复平面上各个点的

分散速度。

经过给定的迭代次数后,若产生的复值保持在圆范围内,则计算过程停止,并且序列也不

发散,本例程生成 Julia 分形图片的代码如下:

#define
ITERATION
128
//迭代次数
#define
REAL_CONSTANT
0.285f
//实部常量
#define
IMG_CONSTANT
0.01f
//虚部常量
//产生 Julia 分形图形
//size_x,size_y:屏幕 x,y 方向的尺寸
//offset_x,offset_y:屏幕 x,y 方向的偏移
//zoom:缩放因子
void GenerateJulia_fpu(u16 size_x,u16 size_y,u16 offset_x,u16 offset_y,u16 zoom)
{
u8 i;
u16 x,y;
float tmp1,tmp2;
float num_real,num_img;
float radius;
for(y=0;y<size_y;y++)
{for(x=0;x<size_x;x++)
{
num_real=y-offset_y;
num_real=num_real/zoom;num_img=x-offset_x;num_img=num_img/zoom;i=0;radius=0;while((i<ITERATION-1)&&(radius<4)){
tmp1=num_real*num_real;tmp2=num_img*num_img;num_img=2*num_real*num_img+IMG_CONSTANT;
num_real=tmp1-tmp2+REAL_CONSTANT;radius=tmp1+tmp2;i++;}
if(lcdltdc.pwidth!=0)lcdbuf[lcddev.width-x-1]=color_map[i];
//保存颜色值到 lcdbuf
else LCD->LCD_RAM=color_map[i];//绘制到屏幕}
if(lcdltdc.pwidth!=0)LTDC_Color_Fill(0,y,lcddev.width-1,y,lcdbuf); //DM2D 填充
}
}

这种算法非常有效地展示了 FPU 的优势:无需修改代码,只需在编译阶段激活或禁止

FPU(在 MDK 的 Float Point Hardware 选项里面设置:Use Double Precision/Not Used),即可

测试使用硬件 FPU 和不使用硬件 FPU 的差距。

注意,是该函数将颜色数据填充到 LCD 的时候,根据 MCU 屏还是 RGB 屏,做了不同的

处理:MCU 屏可以直接写 LCD_RAM,将颜色显示到 LCD 上面;而 RGB 屏,则需要先缓存

到 lcdbuf,然后通过 DMA2D 一次性填充,以提高速度。

50.2 硬件设计

本章实验功能简介:开机后,根据迭代次数生成颜色表(RGB565),然后计算 Julia 分形,

并显示到 LCD 上面。同时,程序开启了定时器 3,用于统计一帧所要的时间(ms),在一帧

Julia 分形图片显示完成后,程序会显示运行时间、当前是否使用 FPU 和缩放因子(zoom)等

信息,方便观察对比。KEY0/KEY2 用于调节缩放因子,KEY_UP 用于设置自动缩放,还是手

动缩放。DS0 用于提示程序运行状况。

本实验用到的资源如下:

1,指示灯 DS0

2,三个按键(KEY_UP/KEY0/KEY2)

3,串口

4,LCD 模块

这些前面都已介绍过。

50.3 软件设计

本章代码,分成两个工程:

1,实验 45_1 FPU 测试(Julia 分形)实验_开启硬件 FPU

2,实验 45_2 FPU 测试(Julia 分形)实验_关闭硬件 FPU

这两个工程的代码一模一样,只是前者使用硬件 FPU 计算 Julia 分形集(MDK 设置 Use

Double Precision),后者使用 IEEE-754 标准计算 Julia 分形集(MDK 设置 Not Used)。由于两

个工程代码一模一样,我们这里仅介绍其中一个:实验 45_1 FPU 测试(Julia 分形)实验_开启硬

件 FPU。

本章代码,我们在 TFTLCD 显示实验的基础上修改,打开 TFTLCD 显示实验的工程,由

于要统计帧时间和按键设置,所以在 HARDWARE 组下加入 timer.c 和 key.c 两个文件。

本章不需要添加其他.c 文件,所有代码均在 main.c 里面实现,整个代码如下:

//FPU 模式提示
#if __FPU_USED==1
#define SCORE_FPU_MODE "FPU On"
#else
#define SCORE_FPU_MODE "FPU Off"
#endif
#define
ITERATION
128
//迭代次数
#define
REAL_CONSTANT
0.285f
//实部常量
#define
IMG_CONSTANT
0.01f
//虚部常量
//颜色表
u16 color_map[ITERATION];
//缩放因子列表
const u16 zoom_ratio[] =
{
120, 110, 100, 150, 200, 275, 350, 450,
600, 800, 1000, 1200, 1500, 2000, 1500,
1200, 1000, 800, 600, 450, 350, 275, 200,
150, 100, 110,
};
//初始化颜色表
//clut:颜色表指针
void InitCLUT(u16 * clut)
{
u32 i=0x00;
u16 red=0,green=0,blue=0;
for(i=0;i<ITERATION;i++)//产生颜色表
{
//产生 RGB 颜色值
red=(i*8*256/ITERATION)%256;
green=(i*6*256/ITERATION)%256;
blue=(i*4*256 /ITERATION)%256;
//将 RGB888,转换为 RGB565
red=red>>3;
red=red<<11;
green=green>>2;
green=green<<5;
blue=blue>>3;
clut[i]=red+green+blue;
}
}
//产生 Julia 分形图形
//size_x,size_y:屏幕 x,y 方向的尺寸
//offset_x,offset_y:屏幕 x,y 方向的偏移
//zoom:缩放因子
void GenerateJulia_fpu(u16 size_x,u16 size_y,u16 offset_x,u16 offset_y,u16 zoom)
{
……//代码省略,详见 53.1.2 节
}
u8 timeout;
int main(void)
{u8 key, i=0, autorun=0;
float time;
u8 buf[50];Cache_Enable(); //打开 L1-Cache
HAL_Init();//初始化 HAL 库Stm32_Clock_Init(432,25,2,9); //设置时钟,216Mhzdelay_init(216); //延时初始化
uart_init(115200);//串口初始化LED_Init(); //初始化 LEDKEY_Init(); //初始化按键SDRAM_Init(); //初始化 SDRAMLCD_Init(); //LCD 初始化TIM3_Init(65535,10800-1); //10Khz 计数频率,最大计时 6.5 秒超出
……//此处省略部分代码
InitCLUT(color_map); //初始化颜色表
while(1)
{
key=KEY_Scan(0);
switch(key)
{
case KEY0_PRES:
i++;
if(i>sizeof(zoom_ratio)/2-1)i=0;//限制范围
break;
case KEY2_PRES:
if(i)i--;
else i=sizeof(zoom_ratio)/2-1;
break;
case WKUP_PRES:
autorun=!autorun; //自动/手动
break;
}
if(autorun==1)//自动时,自动设置缩放因子
{
i++;
if(i>sizeof(zoom_ratio)/2-1)i=0;//限制范围
}
LCD_Set_Window(0,0,lcddev.width,lcddev.height);//设置窗口
LCD_WriteRAM_Prepare();__HAL_TIM_SET_COUNTER(&TIM3_Handler,0);//重设 TIM3 定时器的计数器值
timeout=0;
GenerateJulia_fpu(lcddev.width,lcddev.height,lcddev.width/2,
lcddev.height/2,zoom_ratio[i]);time=__HAL_TIM_GET_COUNTER(&TIM3_Handler)+(u32)timeout*65536;
sprintf((char*)buf,"%s: zoom:%d runtime:%0.1fmsrn",
SCORE_FPU_MODE,zoom_ratio[i],time/10);
LCD_ShowString(5,lcddev.height-5-12,lcddev.width-5,12,12,buf);//显示运行情况
printf("%s",buf);//输出到串口
LED0_Toggle;
}
}
这里面,总共 3 个函数:InitCLUT、GenerateJulia_fpu 和 main 函数。

InitCLUT 函数,该函数用于初始化颜色表,该函数根据迭代次数(ITERATION)计算出颜

色表,这些颜色值将显示在 TFTLCD 上。

GenerateJulia_fpu 函数,该函数根据给定的条件计算 Julia 分形集,当迭代次数大于等于

ITERATION 或者半径大于等于 4 时,结束迭代,并在 TFTLCD 上面显示迭代次数对应的颜色

值,从而得到漂亮的 Julia 分形图。我们可以通过修改 REAL_CONSTANT 和 IMG_CONSTANT

这两个常量的值来得到不同的 Julia 分形图。

main 函数,完成我们在 56.2 节所介绍的实验功能,代码比较简单。这里我们用到一个缩放

因子表:zoom_ratio,里面存储了一些不同的缩放因子,方便演示效果。

最后,为了提高速度,同上一章一样,我们在 MDK 里面选择使用-O2 优化,优化代码速

度,本例程代码就介绍到这里。

再次提醒大家:本例程两个代码(实验 45_1 和 45_2)程序是完全一模一样的,他们的区

别就是 MDK→Options for Target ‘Target1’→Target 选项卡→Floating Point Hardware 的设置不

一样,当设置 Use Double Precision 时,使用硬件 FPU;当设置 Not Used 时,不使用硬件 FPU。

分别下载这两个代码,通过屏幕显示的 runtime 时间,即可看出速度上的区别。

50.4 下载验证

代码编译成功之后,下载本例程任意一个代码(这里以 45_1 为例)到 ALIENTEK 水星

STM32 开发板上,可以看到 LCD 显示 Julia 分形图,并显示相关参数,如图 50.4.1 所示:

图 50.4.1 Julia 分形显示效果

实验 45_1 是开启了硬件 FPU 的,所以显示 Julia 分形图片速度比较快。如果下载实验 45_2,

同样的缩放因子,会比实验 51_1 慢 11 倍左右。

因此可以看出,使用硬件 FPU 和不使用硬件 FPU 对比,同样的条件下,硬件 FPU 快了近

11 倍,充分体现了 STM32F767 硬件 FPU 的优势。

fpu测试_正点原子STM32F4/F7水星开发板资料连载第五十章 FPU 测试实验相关推荐

  1. pdfstamper生成pdf无法显示汉字_正点原子STM32F4/F7水星开发板资料连载第四十六章 汉字显示实验...

    1)实验平台:正点原子水星 STM32F4/F7 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载 ...

  2. 光盘显示0字节可用_正点原子STM32F4/F7水星开发板资料连载第四十六章 汉字显示实验

    1)实验平台:正点原子水星 STM32F4/F7 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载 ...

  3. hal库开启中断关中断_「正点原子NANO STM32开发板资料连载」第十章 外部中断实验...

    1)实验平台:ALIENTEK NANO STM32F411 V1开发板 2)摘自<正点原子STM32F4 开发指南(HAL 库版>关注官方微信号公众号,获取更多资料:正点原子 第十章 外 ...

  4. 正点原子阿波罗STM32F429开发板资料发布,采用底板+核心板

    正点原子阿波罗STM32F429开发板资料发布,采用底板+核心板.... https://www.amobbs.com/thread-5654611-1-1.html 正点原子STM32开发板 htt ...

  5. stm32 ucosii消息队列 串口_正点原子STM32F407探索者开发板资料连载第六十三章 UCOSII 实验...

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 http://weix ...

  6. stm32f407 spi3 mosi没有输出_正点原子STM32F407探索者开发板资料连载第56章 USB 读卡器实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第五十六章 USB 读 ...

  7. 实验5-9 使用函数输出水仙花数_正点原子STM32F407探索者开发板资料连载第五十三章 手写识别实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板 2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第五十三章 手写识别实 ...

  8. fpga驱动rgb液晶屏_正点原子开拓者FPGA开发板资料连载第五十四章基于的数字识别实验...

    1)实验平台:正点原子开拓者FPGA 开发板 2)摘自<开拓者FPGA开发指南>关注官方微信号公众号,获取更多资料:正点原子 3)全套实验源码+手册+视频下载地址:http://www.o ...

  9. 485串口测试工具软件_探索者 STM32F407 开发板资料连载第三十一章 485 实验

    1)实验平台:alientek 阿波罗 STM32F767 开发板2)摘自<STM32F7 开发指南(HAL 库版)>关注官方微信号公众号,获取更多资料:正点原子 第三十一章 485 实验 ...

最新文章

  1. Shell的作用与分类
  2. Oracle Database 9i 10g 11g编程艺术 深入数据库体系结构 第2版pdf
  3. 春招不迷茫,模板刷题101实验室上线啦
  4. 语言中拟合函数 计算aic_Go语言函数深度解析(中)
  5. python程序题斐波那契数列_Python编程题9--斐波那契数列
  6. vue 多点触控手势_手写 Vue 手势组件__Vue.js
  7. 美股涨跌幅限制是多少?
  8. L325 如何睡觉
  9. unity3d贪吃蛇游戏源码,支持安卓+IOS双端 unity2019 C#语言开发
  10. Quartus手动生成波形图(以38译码器为例)VHDL
  11. 2.1 对称密钥的生成及以对象序列化方式保存
  12. Minecraft Forge Mod 开发笔记
  13. 二维点云拉普拉斯深度平滑算法-matlab
  14. 解决Mac绿联 拓展坞 网线接口无法使用问题
  15. JavaWeb Day02(动力节点)
  16. [转帖]AMD第三代锐龙处理器首发评测:i9已无力招架
  17. mysql代码check约束_CHECK约束(示例代码)
  18. 剑侠世界2手游为什么不显示服务器,《剑侠世界2》手游好玩不好玩?这篇采访全都告诉你...
  19. 国产报表工具的十八年
  20. 2021年全球与中国先进的CT机行业市场规模及发展前景分析

热门文章

  1. 山下英子与家政学员亲密接触 深度解读断舍离生活美学
  2. 小程序开发------文件目录结构
  3. 2021年6月大学英语六级作文
  4. python import turtle as t_turtle库的学习笔记(python)
  5. IPadDemo之QQZone
  6. Android开发学习总结(四)——Eclipse在线安装ADT插件
  7. Lisa美语发音教程——学习笔记
  8. 看报记账打字查地图,10款有效提高你生活质量的app
  9. 掌握这些电脑知识,你会玩得很无耻
  10. Docker 安装常用软件(超全、超实用)