原创 【博客大赛】在STM32F746DISC上显示分形

2016-5-6 10:50 1253 15 12 分类: MCU/ 嵌入式
这个程序演示了在STM32F746DISC开发板上显示分形(MandelBrot set),实现了缩放、移动、参数显示等功能。一个手指可以拖动图形,两个手指靠近或分开可以缩放。
 
此外使用了Guess算法减少计算次数,加快显示速度。
 
1.jpg2.jpg3.jpg4.jpg7.jpg
 
 
参考代码:
 
#include "mbed.h"
#include "LCD_DISCO_F746NG.h"
#include "TS_DISCO_F746NG.h"
#include <math.h>
 
#define ITERATION  150
#define BAILOUT 4
 
LCD_DISCO_F746NG lcd;
TS_DISCO_F746NG ts;
TS_StateTypeDef TS_State;
uint8_t ts_nb = 0;
 
uint16_t tsx0[2], tsy0[2];
uint16_t tsx[2], tsy[2];
uint8_t tscnt = 0;
double zoom = 1;
 
Timer tmr;
 
uint8_t msg[20];
uint16_t screen_width, screen_height;
 
double mx1, my1, mx2, my2;
 
uint16_t calcMandelBrot(double x, double y)
{
    uint16_t i;
    double xx, yy, tx, ty;
    
    xx = yy = 0;
    i = 0;
    while((i < ITERATION) && ((xx*xx + yy*yy) < BAILOUT))
    {
        tx = xx*xx - yy*yy + x;
        ty = 2*xx*yy + y;
        xx = tx;
        yy = ty;
        i++;
    }
    return i;
}
 
uint8_t c[150][100];
void rectMandelBrot(double x1, double y1, double x2, double y2)
{
    double dx, dy;
    uint16_t i, j, n;
    uint32_t color;
  
    lcd.SetTextColor(LCD_COLOR_BLACK);
    lcd.FillRect(0, 0, screen_width, screen_height);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    sprintf((char *)msg, "%10f", x1);
    lcd.DisplayStringAt(screen_width+5, 224, msg, LEFT_MODE);
    sprintf((char *)msg, "%10f", y1);
    lcd.DisplayStringAt(screen_width+5, 236, msg, LEFT_MODE);
    sprintf((char *)msg, "%10f", x2);
    lcd.DisplayStringAt(screen_width+5, 248, msg, LEFT_MODE);
    sprintf((char *)msg, "%10f", y2);
    lcd.DisplayStringAt(screen_width+5, 260, msg, LEFT_MODE);
    sprintf((char *)msg, "  %10f", zoom);
    lcd.DisplayStringAt(screen_width+5, 212, msg, LEFT_MODE);
    
    tmr.reset();
    tmr.start();
    
    dx = (x2 - x1)/screen_width;
    dy = (y2 - y1)/screen_height;
/*
    for(i = 0; i < screen_width; i++)
    {
        for(j = 0; j < screen_height; j++)
        {
            color = calcMandelBrot(x1 + dx*i, y1 + dy*j);
            lcd.DrawPixel(i, j, 0xFF000000 | (color<<14) | (color <<4));
        }
    }*/
    for(i = 0; i < screen_width/4; i++)
    {
        ts.GetState(&TS_State);
        if (TS_State.touchDetected)
            return;
        for(j = 0; j < screen_height/4; j++)
        {
            c[j] = calcMandelBrot(x1 + 4*dx*i, y1 + 4*dy*j);
            lcd.DrawPixel(4*i, 4*j, 0xFF000000 | (c[j]<<4));
        }
    }
    
    for(i = 0; i < screen_width/4; i++)
    {
        ts.GetState(&TS_State);
        if (TS_State.touchDetected)
            return;
        for(j = 0; j < screen_height/4; j++)
        {
            if((c[j] == c[i+1][j]) && (c[j] == c[i+1][j+1]) && (c[j] == c[j+1]))
            {
                lcd.SetTextColor(0xFF000000 | (c[j]<<4));
                lcd.FillRect(i*4, j*4, 4, 4);                
            }
            else
            {
                for(n = 1; n < 16; n++)
                {
                    color = calcMandelBrot(x1 + dx*(4*i+(n/4)), y1 + dy*(4*j+(n%4)));
                    lcd.DrawPixel(4*i+(n/4), 4*j+(n%4), 0xFF000000 | (color<<4));
                }
            }
        }
    }
 
    tmr.stop();
    
    sprintf((char *)msg, "  %6d ms", tmr.read_ms());
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.SetBackColor(LCD_COLOR_BLACK);
    lcd.DisplayStringAt(screen_width+5, 20, msg, LEFT_MODE);
}
 
int main()
{
    uint8_t status;
    uint8_t prev_nb_touches = 0;
    double cx, cy, lx, ly;
 
    status = ts.Init(lcd.GetXSize(), lcd.GetYSize()); 
    if (status != TS_OK) {
        lcd.Clear(LCD_COLOR_RED);
        lcd.SetBackColor(LCD_COLOR_RED);
        lcd.SetTextColor(LCD_COLOR_WHITE);
        lcd.DisplayStringAt(0, LINE(5), (uint8_t *)"TOUCHSCREEN INIT FAIL", CENTER_MODE);
        
        while(1);
    }    
    
    lcd.Clear(LCD_COLOR_BLACK);
    lcd.SetFont(&Font12);
    lcd.SetTextColor(LCD_COLOR_WHITE);
    lcd.SetBackColor(LCD_COLOR_BLACK);
 
    screen_width = lcd.GetXSize() - 120;
    screen_height = lcd.GetYSize();
 
    lcd.DisplayStringAt(screen_width+5, 0, (uint8_t *)"Elapsed:", LEFT_MODE);
    lcd.DisplayStringAt(screen_width+5, 200, (uint8_t *)"Zoom:", LEFT_MODE);
 
    
    mx1 = -2.5;
    my1 = -2.5;
    mx2 = 2.5;
    my2 = 2.5;
    rectMandelBrot(mx1, my1, mx2, my2);
    
    status = 0;
    while(1)
    {
        wait(0.01);
        ts.GetState(&TS_State);
        if (TS_State.touchDetected)
        {
            if(TS_State.touchDetected != prev_nb_touches)
            {
                status = 0;
                tscnt = 0;
                prev_nb_touches = TS_State.touchDetected;                
            }
            
            if(tscnt < 10)
            {
                tscnt++;
                if(tscnt == 9)
                {
                    ts_nb = TS_State.touchDetected;
                    lcd.SetTextColor(LCD_COLOR_BLACK);
                    lcd.FillRect(screen_width+5, 60, 120, 48);
                }
                continue;
            }
            
            switch(ts_nb)
            {
                case 1:
                    if(status == 0)
                    {
                        status = 1;
                        tsx0[0] = TS_State.touchX[0];
                        tsy0[0] = TS_State.touchY[0];
                    }
                    tsx[0] = TS_State.touchX[0];
                    tsy[0] = TS_State.touchY[0];
                    lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);
                    sprintf((char *)msg, "%3d", TS_State.touchX[0]);
                    lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);
                    sprintf((char *)msg, "%3d", TS_State.touchY[0]);
                    lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);
                    break;
                case 2:
                    if(status == 0)
                    {
                        status = 1;
                        tsx0[0] = TS_State.touchX[0];
                        tsy0[0] = TS_State.touchY[0];
                        tsx0[1] = TS_State.touchX[1];
                        tsy0[1] = TS_State.touchY[1];
                    }
                    tsx[0] = TS_State.touchX[0];
                    tsy[0] = TS_State.touchY[0];
                    tsx[1] = TS_State.touchX[1];
                    tsy[1] = TS_State.touchY[1];
                    lcd.SetTextColor(LCD_COLOR_LIGHTBLUE);
                    sprintf((char *)msg, "%3d", TS_State.touchX[0]);
                    lcd.DisplayStringAt(screen_width+5, 60, msg, LEFT_MODE);
                    sprintf((char *)msg, "%3d", TS_State.touchY[0]);
                    lcd.DisplayStringAt(screen_width+5, 72, msg, LEFT_MODE);
                    sprintf((char *)msg, "%3d", TS_State.touchX[1]);
                    lcd.DisplayStringAt(screen_width+5, 84, msg, LEFT_MODE);
                    sprintf((char *)msg, "%3d", TS_State.touchY[1]);
                    lcd.DisplayStringAt(screen_width+5, 96, msg, LEFT_MODE);
                    break;
            }
        }
        else
        {
            if(status)
            {
                lcd.SetTextColor(LCD_COLOR_YELLOW);
                status = 0;
                tscnt = 0;
                switch(ts_nb)
                {
                    case 1:
                        if((abs(tsx[0] - tsx0[0]) > 20) || (abs(tsy[0] - tsy0[0]) > 20))
                        {
                            lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)" - ", LEFT_MODE);
                            cx = (tsx[0] - tsx0[0])*(mx2 - mx1)/screen_width;
                            cy = (tsy[0] - tsy0[0])*(my2 - my1)/screen_height;
                            mx1 -= cx;
                            mx2 -= cx;
                            my1 -= cy;
                            my2 -= cy;
                            rectMandelBrot(mx1, my1, mx2, my2);
                        }
                        break;
                    case 2:
                        if(((tsx[0]-tsx[1])*(tsx[0]-tsx[1]) + 20) < ((tsx0[0]-tsx0[1])*(tsx0[0]-tsx0[1])))
                        {
                            lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"out", LEFT_MODE);
                            zoom = zoom /2;
                            cx = (tsx0[0] + tsx0[1])/2;
                            cy = (tsy0[0] + tsy0[1])/2;
                            lx = (mx2 - mx1);
                            ly = (my2 - my1);
                            cx = cx * (mx2 - mx1) / screen_width + mx1;
                            cy = cy * (my2 - my1) / screen_height + my1;
                            mx1 = cx - lx;
                            mx2 = cx + lx;
                            my1 = cy - ly;
                            my2 = cy + ly;
                            rectMandelBrot(mx1, my1, mx2, my2);                            
                        }
                        else if(((tsx[0]-tsx[1])*(tsx[0]-tsx[1])) > ((tsx0[0]-tsx0[1])*(tsx0[0]-tsx0[1]) + 20))
                        {
                            lcd.DisplayStringAt(screen_width+41, 200, (uint8_t *)"in ", LEFT_MODE);
                            zoom = zoom*2;
                            cx = (tsx0[0] + tsx0[1])/2;
                            cy = (tsy0[0] + tsy0[1])/2;
                            lx = (mx2 - mx1)/4;
                            ly = (my2 - my1)/4;
                            cx = cx * (mx2 - mx1) / screen_width + mx1;
                            cy = cy * (my2 - my1) / screen_height + my1;
                            mx1 = cx - lx;
                            mx2 = cx + lx;
                            my1 = cy - ly;
                            my2 = cy + ly;
                            rectMandelBrot(mx1, my1, mx2, my2);  
                            
                        }
 
                        break;
                }
            }
        }
 
 
    }
}
 
 
目前已知问题,手势识别还不够灵敏,等待进一步改进。
 
 

文章评论1条评论)

登录后参与讨论

用户468979 2016-5-10 14:40

太漂亮了!!!!!!!!

用户1053025 2008-6-10 15:12

Altium又有新产品了,呵呵,这次是用C就可以实现的编程
相关推荐阅读
shaoziyang 2017-12-15 11:06
《micropython 入门指南》正式出版了
第一本专门介绍MicroPython的中文图书《MicroPython入门指南》由电子工业出版社正式出版了(各大书店和网络书店都有)。MicroPython是近年开源社区中最热门的项目之一,它功能强大...
shaoziyang 2017-11-01 15:30
《MicoPython入门指南》一书即将发行
《MicoPython入门指南》一书即将发行,这是第一本专业介绍MicroPython的中文书籍,请大家多关注和支持。​​...
shaoziyang 2017-07-13 19:50
micro:bit 专用电池扩展板
最近Microbit这么火,就想着要做点什么,于是就有了这个Microbit的专用电池扩展板。它完美配合原版的microbit,可以为microbit增加电池、蜂鸣器功能,功能上超过 MI:power...
shaoziyang 2017-06-13 09:09
用pyboard的dac播放音乐
官方的PyBoard带有DAC功能,使用DAC,我们可以播放简单的音乐。 先准备好两根铜丝,一个有源音箱,一个音频线。 然后从官方网站下载两个文件: http://micropython.org/...
shaoziyang 2017-06-13 09:03
microbit巡线小车 BoBBoT
BoBBoT 是一个使用 BBC micro:bit 控制的巡线小车套件,它很容易组装。 它特别为儿童设计,让孩子可以通过实践学习计算机科学概念。使用 BoBBoT 可以学习: 算法设计 (流程图和...
shaoziyang 2017-06-12 08:29
micropython升级到了 1.9.1
micropython升级到了 1.9.1,主要改进有: v1.9.1 修复了 stm32 的 USB 存储, lwIP 绑定和 VFS 问题 This release provides an imp...
我要评论
1
15
关闭 站长推荐上一条 /2 下一条