你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【STM32F746DISC】显示分形2

[复制链接]
shaoziyang 发布时间:2016-5-6 10:21
这是昨天程序的升级版,增加了缩放、移动、参数显示等功能。一个手指可以拖到图形,两个手指靠近或分开可以缩放。

此外使用了Guess算法减少计算次数,加快显示速度。

目前已知问题,手势识别还不够灵敏,等待进一步改进。

1.jpg 2.jpg 3.jpg 4.jpg 5.jpg 6.jpg 7.jpg

  1. #include "mbed.h"
  2. #include "LCD_DISCO_F746NG.h"
  3. #include "TS_DISCO_F746NG.h"
  4. #include <math.h>

  5. #define ITERATION  150
  6. #define BAILOUT 4

  7. LCD_DISCO_F746NG lcd;
  8. TS_DISCO_F746NG ts;
  9. TS_StateTypeDef TS_State;
  10. uint8_t ts_nb = 0;

  11. uint16_t tsx0[2], tsy0[2];
  12. uint16_t tsx[2], tsy[2];
  13. uint8_t tscnt = 0;
  14. double zoom = 1;

  15. Timer tmr;

  16. uint8_t msg[20];
  17. uint16_t screen_width, screen_height;

  18. double mx1, my1, mx2, my2;

  19. uint16_t calcMandelBrot(double x, double y)
  20. {
  21.     uint16_t i;
  22.     double xx, yy, tx, ty;
  23.    
  24.     xx = yy = 0;
  25.     i = 0;
  26.     while((i < ITERATION) && ((xx*xx + yy*yy) < BAILOUT))
  27.     {
  28.         tx = xx*xx - yy*yy + x;
  29.         ty = 2*xx*yy + y;
  30.         xx = tx;
  31.         yy = ty;
  32.         i++;
  33.     }
  34.     return i;
  35. }

  36. uint8_t c[150][100];
  37. void rectMandelBrot(double x1, double y1, double x2, double y2)
  38. {
  39.     double dx, dy;
  40.     uint16_t i, j, n;
  41.     uint32_t color;
  42.   
  43.     lcd.SetTextColor(LCD_COLOR_BLACK);
  44.     lcd.FillRect(0, 0, screen_width, screen_height);
  45.     lcd.SetTextColor(LCD_COLOR_WHITE);
  46.     sprintf((char *)msg, "%10f", x1);
  47.     lcd.DisplayStringAt(screen_width+5, 224, msg, LEFT_MODE);
  48.     sprintf((char *)msg, "%10f", y1);
  49.     lcd.DisplayStringAt(screen_width+5, 236, msg, LEFT_MODE);
  50.     sprintf((char *)msg, "%10f", x2);
  51.     lcd.DisplayStringAt(screen_width+5, 248, msg, LEFT_MODE);
  52.     sprintf((char *)msg, "%10f", y2);
  53.     lcd.DisplayStringAt(screen_width+5, 260, msg, LEFT_MODE);
  54.     sprintf((char *)msg, "  %10f", zoom);
  55.     lcd.DisplayStringAt(screen_width+5, 212, msg, LEFT_MODE);
  56.    
  57.     tmr.reset();
  58.     tmr.start();
  59.    
  60.     dx = (x2 - x1)/screen_width;
  61.     dy = (y2 - y1)/screen_height;
  62. /*
  63.     for(i = 0; i < screen_width; i++)
  64.     {
  65.         for(j = 0; j < screen_height; j++)
  66.         {
  67.             color = calcMandelBrot(x1 + dx*i, y1 + dy*j);
  68.             lcd.DrawPixel(i, j, 0xFF000000 | (color<<14) | (color <<4));
  69.         }
  70.     }*/
  71.     for(i = 0; i < screen_width/4; i++)
  72.     {
  73.         ts.GetState(&TS_State);
  74.         if (TS_State.touchDetected)
  75.             return;
  76.         for(j = 0; j < screen_height/4; j++)
  77.         {
  78.             c[i][j] = calcMandelBrot(x1 + 4*dx*i, y1 + 4*dy*j);
  79.             lcd.DrawPixel(4*i, 4*j, 0xFF000000 | (c[i][j]<<4));
  80.         }
  81.     }
  82.    
  83.     for(i = 0; i < screen_width/4; i++)
  84.     {
  85.         ts.GetState(&TS_State);
  86.         if (TS_State.touchDetected)
  87.             return;
  88.         for(j = 0; j < screen_height/4; j++)
  89.         {
  90.             if((c[i][j] == c[i+1][j]) && (c[i][j] == c[i+1][j+1]) && (c[i][j] == c[i][j+1]))
  91.             {
  92.                 lcd.SetTextColor(0xFF000000 | (c[i][j]<<4));
  93.                 lcd.FillRect(i*4, j*4, 4, 4);               
  94.             }
  95.             else
  96.             {
  97.                 for(n = 1; n < 16; n++)
  98.                 {
  99.                     color = calcMandelBrot(x1 + dx*(4*i+(n/4)), y1 + dy*(4*j+(n%4)));
  100.                     lcd.DrawPixel(4*i+(n/4), 4*j+(n%4), 0xFF000000 | (color<<4));
  101.                 }
  102.             }
  103.         }
  104.     }

  105.     tmr.stop();
  106.    
  107.     sprintf((char *)msg, "  %6d ms", tmr.read_ms());
  108.     lcd.SetTextColor(LCD_COLOR_WHITE);
  109.     lcd.SetBackColor(LCD_COLOR_BLACK);
  110.     lcd.DisplayStringAt(screen_width+5, 20, msg, LEFT_MODE);
  111. }

  112. int main()
  113. {
  114.     uint8_t status;
  115.     uint8_t prev_nb_touches = 0;
  116.     double cx, cy, lx, ly;

  117.     status = ts.Init(lcd.GetXSize(), lcd.GetYSize());
  118.     if (status != TS_OK) {
  119.         lcd.Clear(LCD_COLOR_RED);
  120.         lcd.SetBackColor(LCD_COLOR_RED);
  121.         lcd.SetTextColor(LCD_COLOR_WHITE);
  122.         lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE);
  123.         
  124.         while(1);
  125.     }   
  126.    
  127.     lcd.Clear(LCD_COLOR_BLACK);
  128.     lcd.SetFont(&Font12);
  129.     lcd.SetTextColor(LCD_COLOR_WHITE);
  130.     lcd.SetBackColor(LCD_COLOR_BLACK);

  131.     screen_width = lcd.GetXSize() - 120;
  132.     screen_height = lcd.GetYSize();

  133.     lcd.DisplayStringAt(screen_width+5, 0, (uint8_t *)"Elapsed:", LEFT_MODE);
  134.     lcd.DisplayStringAt(screen_width+5, 200, (uint8_t *)"Zoom:", LEFT_MODE);

  135.    
  136.     mx1 = -2.5;
  137.     my1 = -2.5;
  138.     mx2 = 2.5;
  139.     my2 = 2.5;
  140.     rectMandelBrot(mx1, my1, mx2, my2);
  141.    
  142.     status = 0;
  143.     while(1)
  144.     {
  145.         wait(0.01);
  146.         ts.GetState(&TS_State);
  147.         if (TS_State.touchDetected)
  148.         {
  149.             if(TS_State.touchDetected != prev_nb_touches)
  150.             {
  151.                 status = 0;
  152.                 tscnt = 0;
  153.                 prev_nb_touches = TS_State.touchDetected;               
  154.             }
  155.             
  156.             if(tscnt < 10)
  157.             {
  158.                 tscnt++;
  159.                 if(tscnt == 9)
  160.                 {
  161.                     ts_nb = TS_State.touchDetected;
  162.                     lcd.SetTextColor(LCD_COLOR_BLACK);
  163.                     lcd.FillRect(screen_width+5, 60, 120, 48);
  164.                 }
  165.                 continue;
  166.             }
  167.             
  168.             switch(ts_nb)
  169.             {
  170.                 case 1:
  171.                     if(status == 0)
  172.                     {
  173.                         status = 1;
  174.                         tsx0[0] = TS_State.touchX[0];
  175.                         tsy0[0] = TS_State.touchY[0];
  176.                     }
  177.                     tsx[0] = TS_State.touchX[0];
  178.                     tsy[0] = TS_State.touchY[0];
  179.                     lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);
  180.                     sprintf((char *)msg, "%3d", TS_State.touchX[0]);
  181.                     lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);
  182.                     sprintf((char *)msg, "%3d", TS_State.touchY[0]);
  183.                     lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);
  184.                     break;
  185.                 case 2:
  186.                     if(status == 0)
  187.                     {
  188.                         status = 1;
  189.                         tsx0[0] = TS_State.touchX[0];
  190.                         tsy0[0] = TS_State.touchY[0];
  191.                         tsx0[1] = TS_State.touchX[1];
  192.                         tsy0[1] = TS_State.touchY[1];
  193.                     }
  194.                     tsx[0] = TS_State.touchX[0];
  195.                     tsy[0] = TS_State.touchY[0];
  196.                     tsx[1] = TS_State.touchX[1];
  197.                     tsy[1] = TS_State.touchY[1];
  198.                     lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);
  199.                     sprintf((char *)msg, "%3d", TS_State.touchX[0]);
  200.                     lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);
  201.                     sprintf((char *)msg, "%3d", TS_State.touchY[0]);
  202.                     lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);
  203.                     sprintf((char *)msg, "%3d", TS_State.touchX[1]);
  204.                     lcd.DisplayStringAt(screen_width+5, 84, msg, LEFT_MODE);
  205.                     sprintf((char *)msg, "%3d", TS_State.touchY[1]);
  206.                     lcd.DisplayStringAt(screen_width+5, 96, msg, LEFT_MODE);
  207.                     break;
  208.             }
  209.         }
  210.         else
  211.         {
  212.             if(status)
  213.             {
  214.                 lcd.SetTextColor(LCD_COLOR_YELLOW);
  215.                 status = 0;
  216.                 tscnt = 0;
  217.                 switch(ts_nb)
  218.                 {
  219.                     case 1:
  220.                         if((abs(tsx[0] - tsx0[0]) > 20) || (abs(tsy[0] - tsy0[0]) > 20))
  221.                         {
  222.                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)" - ", LEFT_MODE);
  223.                             cx = (tsx[0] - tsx0[0])*(mx2 - mx1)/screen_width;
  224.                             cy = (tsy[0] - tsy0[0])*(my2 - my1)/screen_height;
  225.                             mx1 -= cx;
  226.                             mx2 -= cx;
  227.                             my1 -= cy;
  228.                             my2 -= cy;
  229.                             rectMandelBrot(mx1, my1, mx2, my2);
  230.                         }
  231.                         break;
  232.                     case 2:
  233.                         if(((tsx[0]-tsx[1])*(tsx[0]-tsx[1]) + 20) < ((tsx0[0]-tsx0[1])*(tsx0[0]-tsx0[1])))
  234.                         {
  235.                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"out", LEFT_MODE);
  236.                             zoom = zoom /2;
  237.                             cx = (tsx0[0] + tsx0[1])/2;
  238.                             cy = (tsy0[0] + tsy0[1])/2;
  239.                             lx = (mx2 - mx1);
  240.                             ly = (my2 - my1);
  241.                             cx = cx * (mx2 - mx1) / screen_width + mx1;
  242.                             cy = cy * (my2 - my1) / screen_height + my1;
  243.                             mx1 = cx - lx;
  244.                             mx2 = cx + lx;
  245.                             my1 = cy - ly;
  246.                             my2 = cy + ly;
  247.                             rectMandelBrot(mx1, my1, mx2, my2);                           
  248.                         }
  249.                         else if(((tsx[0]-tsx[1])*(tsx[0]-tsx[1])) > ((tsx0[0]-tsx0[1])*(tsx0[0]-tsx0[1]) + 20))
  250.                         {
  251.                             lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"in ", LEFT_MODE);
  252.                             zoom = zoom*2;
  253.                             cx = (tsx0[0] + tsx0[1])/2;
  254.                             cy = (tsy0[0] + tsy0[1])/2;
  255.                             lx = (mx2 - mx1)/4;
  256.                             ly = (my2 - my1)/4;
  257.                             cx = cx * (mx2 - mx1) / screen_width + mx1;
  258.                             cy = cy * (my2 - my1) / screen_height + my1;
  259.                             mx1 = cx - lx;
  260.                             mx2 = cx + lx;
  261.                             my1 = cy - ly;
  262.                             my2 = cy + ly;
  263.                             rectMandelBrot(mx1, my1, mx2, my2);  
  264.                            
  265.                         }

  266.                         break;
  267.                 }
  268.             }
  269.         }


  270.     }
  271. }
复制代码

编译后的BIN文件,可以直接下载运行。 DISCO-F746NG_fract.bin.zip (31.95 KB, 下载次数: 6)
收藏 3 评论8 发布时间:2016-5-6 10:21

举报

8个回答
风子 回答时间:2016-5-6 10:33:41
厉害   
jinglixixi 回答时间:2016-5-6 15:29:56
不错呀!
埃斯提爱慕 回答时间:2016-5-6 22:53:57
提示: 作者被禁止或删除 内容自动屏蔽
suoma 回答时间:2016-5-6 23:42:48
谢谢分享学习一下
shanji 回答时间:2016-5-7 11:44:16
这个好像是朱丽亚碎形几何运算,用来评估CPU单精度浮点运算能力。
shaoziyang 回答时间:2016-5-7 16:38:12
shanji 发表于 2016-5-7 11:44
这个好像是朱丽亚碎形几何运算,用来评估CPU单精度浮点运算能力。

这个是曼德布罗特集的图形,茱莉亚集的计算公式略有不同
yangc9 回答时间:2016-5-9 02:18:03
本帖最后由 yangc9 于 2016-5-9 02:24 编辑

给你提点意见.
一.迭代收敛的条件是,|z|<=2.写成<2会错过一些点,比如(-2,0)
二.仅靠4角同色不足以判断此矩形内同色.可能会在一些半岛周围漏掉几个点.
正确的做法是:
1.每隔4点计算颜色.
2.将4角颜色不同的小矩形标记为pend.
3.计算所有pend矩形内的每个点的颜色.
将此矩形标记为done.
如此矩形不是纯色,将此矩形的4个邻居标记为pend(已是done的除外)
4.重复第3步,直到没有pend.
三.对于有FPU的单片机可以光明正大的用double,但没有FPU的就惨了,软件浮点算法特慢.
可以用定点数,小数点的位置有讲究,s5p26比较合适.比float精度稍高,也没有溢出问题.
要注意的是判断收敛时要当做u6p26来比较,因为|z|最大能到6,|z|2能到36,超出了s5p26的范围,但不会超出u6p26.
shaoziyang 回答时间:2016-5-9 09:57:35
yangc9 发表于 2016-5-9 02:18
给你提点意见.
一.迭代收敛的条件是,|z|

看来也是一个分形高手啊。这个程序的确不严谨,主要目的是为了演示STM32F7DISC开发板的使用,所以有些地方显得有些粗糙了。后续会继续改进,也希望大家一起来讨论和完善。
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版