单片机FPU实验
单片机 :STM32F407
开发板:DMF407电机开发板
平台:keil V5.31
HSE 为8MHZ
HSI为16MHZ
一、开启FPU:
主函数:
int main(void) { uint8_t key; uint8_t i = 0; uint8_t autorun = 0; float time; char buf[50]; HAL_Init(); /* 初始化HAL库 */ sys_stm32_clock_init(336, 8, 2, 7); /* 设置时钟,168Mhz */ delay_init(168); /* 延时初始化 */ usart_init(115200); /* 串口初始化为115200 */ led_init(); /* 初始化LED */ key_init(); /* 初始化按键 */ lcd_init(); /* 初始化LCD */ btim_timx_int_init(65535, 8400 - 1); /* 10Khz计数频率,最大计时6.5秒超出 */ lcd_show_string(30, 50, 200, 16, 16, "STM32", RED); lcd_show_string(30, 70, 200, 16, 16, "FPU TEST", RED); lcd_show_string(30, 90, 200, 16, 16, "ATOM@ALIENTEK", RED); lcd_show_string(30, 110, 200, 16, 16, "KEY0:+ KEY1:-", RED); /* 显示提示信息 */ lcd_show_string(30, 130, 200, 16, 16, "KEY2:AUTO/MANUL", RED); /* 显示提示信息 */ delay_ms(1200); julia_clut_init(g_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 KEY1_PRES: if (i)i--; else i = sizeof(zoom_ratio) / 2 - 1; break; case KEY2_PRES: autorun = !autorun; /* 自动/手动 */ break; default:break; } if (autorun == 1) /* 自动时,自动设置缩放因子 */ { i++; LED1(0); /* 点亮LED1,自动设置 */ if (i > sizeof(zoom_ratio) / 2 - 1) { i = 0; /* 限制范围 */ } } else { LED1(1); /* 熄灭LED1,手动设置 */ } lcd_set_window(0, 0, lcddev.width, lcddev.height); /* 设置窗口 */ lcd_write_ram_prepare(); BTIM_TIMX_INT->CNT = 0; /* 重设TIM6定时器的计数器值 */ g_timeout = 0; julia_generate_fpu(lcddev.width, lcddev.height, lcddev.width / 2, lcddev.height / 2, zoom_ratio[i]); time = BTIM_TIMX_INT->CNT + (uint32_t)g_timeout * 65536; sprintf(buf, "%s: zoom:%d runtime:%0.1fms\r\n", SCORE_FPU_MODE, zoom_ratio[i], time / 10); lcd_show_string(5, lcddev.height - 5 - 12, lcddev.width - 5, 12, 12, buf, RED); /* 显示当前运行情况 */ printf("%s", buf); /* 输出到串口 */ LED0_TOGGLE(); } }Julia分形图形初始化:
void julia_clut_init(uint16_t *clut) { uint32_t i = 0x00; uint16_t 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分形图形:
void julia_generate_fpu(uint16_t size_x, uint16_t size_y, uint16_t offset_x, uint16_t offset_y, uint16_t zoom) { uint8_t i; uint16_t 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++; } LCD->LCD_RAM = g_color_map[i]; /* 绘制到屏幕 */ } } }测试结果:
二、关闭FPU:
可见,关闭FPU后,时间变慢了很多。
Julia集(Julia Set,中文译名朱莉娅集)是分形几何中最经典、最具视觉美感的分形集合之一,由法国数学家加斯顿·朱莉娅在1918年提出,是复平面上通过迭代复变函数生成的非线性分形结构。
Julia集的生成基于二次复迭代函数:
zn+1=zn2+czn+1=zn2+c
其中:
c是一个固定常数(复数),不同的c会生成完全不同形态的Julia集;z_0是复平面上任意一个起点(初始值);- 重复迭代后,如果
z_n的模长始终不超过2(不会发散到无穷远),那么初始点z_0就属于Julia集,否则不属于。
从复动力系统的严格定义来看:Julia集是Fatou集的补集,是系统产生混沌行为的区域,这里初始值的微小扰动会被迭代指数放大,呈现出复杂的自相似分形特征。
经典Julia分形图案示例
不同参数c得到的经典形态:
c = -0.8 + 0.156i:双叶对称分形,是最常见的经典Julia集图案c = 0.11 + 0.66i:类似龙形的螺旋结构c = 0.285 - 0.01i:多分枝的雪花状结构- 四元数Julia分形:扩展到四维空间的分形,渲染后呈现星云般的立体结构。
