22-Graphic-DMA2D-Library (STM32F429)

Diese Library benutzt den internen DMA2D vom STM32F429 für das zeichnen von Linien Rechtecken, Kreisen und Bildern aus dem Flash.

Der DMA2D ist um ein vielfaches schneller wie die gleiche Funktion per “CPU”

z.B. dauert das löschen vom kompletten Screen ohne DMA2D ca. 11ms und mit DMA2D sind es nur noch 1ms

Im Beispiel werden 10.000 Kreise und 10.000 Rechtecke gezeichnet und danach kommt ein Beispiel wie man bewegte Objekte darstellen kann.

Hinweis : die LCD_ILI9341-Lib muss mindestens Version 1.2 sein

Hinweis zur Funktion “UB_Graphic2D_CopyImgDMA”
Der Funktion muss der Bildname und eine Struktur mit den Koordinaten übergeben werden. Mit den Koordinaten wird festgelegt welcher Teilabschnitt vom Bild (sx,sy,w,h) an welcher Position vom Display (dx,dy) angezeigt werden soll.

DMA2D (Memory to Memory) :

DMA2D_M2M

DMA2D_M2M

Beispielbild :

dma2d

Funktionen :

1
2
3
4
5
6
7
8
9
void UB_Graphic2D_ClearSreenDMA(uint16_t c);                                                          // löscht kompletten Screen
void UB_Graphic2D_DrawPixelNormal(uint16_t xp, uint16_t yp, uint16_t c);                              // zeichnet ein Pixel
void UB_Graphic2D_DrawLineNormal(uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color); // zeichnet schräge Linie
void UB_Graphic2D_DrawStraightDMA(uint16_t xp, uint16_t yp, uint16_t l, LCD_DIR_t d, uint16_t c);     // zeichnet Gerade Linie
void UB_Graphic2D_DrawRectDMA(uint16_t xp, uint16_t yp, uint16_t w, uint16_t h, uint16_t c);          // zeichnet Rechteck
void UB_Graphic2D_DrawFullRectDMA(uint16_t xp, uint16_t yp, uint16_t w, uint16_t h, uint16_t c);      // zeichnet gefülltes Rechteck
void UB_Graphic2D_DrawCircleNormal(uint16_t xp, uint16_t yp, uint16_t r, uint16_t c);                 // zeichnet Kreis
void UB_Graphic2D_DrawFullCircleDMA(uint16_t xp, uint16_t yp, uint16_t r, uint16_t c);                // zeichnet gefüllten Kreis
void UB_Graphic2D_CopyImgDMA(UB_Image *img, DMA2D_Koord koord);                                       // zeichnet Teilimage aus dem Flash

Beispiel :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
//--------------------------------------------------------------
// File     : main.c
// Datum    : 26.11.2013
// Version  : 1.1
// Autor    : UB
// EMail    : mc-4u(@)t-online.de
// Web      : www.mikrocontroller-4u.de
// CPU      : STM32F429
// IDE      : CooCox CoIDE 1.7.4
// GCC      : 4.7 2012q4
// Module   : CMSIS_BOOT, M4_CMSIS_CORE
// Funktion : Demo der DMA2D-Graphic-Lib
// Hinweis  : Diese zwei Files muessen auf 8MHz stehen
//              "cmsis_boot/stm32f4xx.h"
//              "cmsis_boot/system_stm32f4xx.c"
// In Configuration diese Define hinzufügen :
// "STM32F429_439xx" , "__ASSEMBLY__" , "USE_STDPERIPH_DRIVER"
//--------------------------------------------------------------
 
#include "main.h"
#include "stm32_ub_lcd_ili9341.h"
#include "stm32_ub_graphic2d.h"
#include <stdlib.h>
 
int main(void)
{
  uint16_t x1,y1,x2,y2,r1,r2,c;
  uint32_t n,m;
  DMA2D_Koord koord;
 
  SystemInit(); // Quarz Einstellungen aktivieren
 
  UB_LCD_Init();
  UB_LCD_LayerInit_Fullscreen();
 
  // auf Vordergrund schalten
  UB_LCD_SetLayer_2();
 
  while(1)
  {
    //-------------------------------
    // 1.) 10.000 Kreise zeichnen
    //-------------------------------
    for(n=0;n<10000;n++) {
      x1=rand() % (LCD_MAXX);
      y1=rand() % (LCD_MAXY);
      r1=rand() % (30);
      c=rand() % (65535);
      UB_Graphic2D_DrawFullCircleDMA(x1,y1,r1,c);
    }
    // kleine Pause
    for(n=0;n<30000000;n++);
    //-------------------------------
    // 2.) 10.000 Rechtecke zeichnen
    //-------------------------------
    for(n=0;n<10000;n++) {
      x1=rand() % (LCD_MAXX);
      y1=rand() % (LCD_MAXY);
      x2=rand() % (LCD_MAXX);
      y2=rand() % (LCD_MAXY);
      c=rand() % (65535);
      UB_Graphic2D_DrawFullRectDMA(x1,y1,x2,y2,c);
    }
    // kleine Pause
    for(n=0;n<30000000;n++);
    //-------------------------------
    // 3.) bewegter Kreis
    //-------------------------------
    r1=0;r2=0;
    x1=111;y1=111;
    for(n=0;n<5000;n++) {
      UB_Graphic2D_ClearSreenDMA(RGB_COL_GREEN);
      UB_Graphic2D_DrawFullCircleDMA(x1,y1,60,RGB_COL_RED);
      UB_LCD_Refresh();
      if(r1==0) {
        x1++;
        if(x1>240-60) r1=1-r1;
      }
      else {
        x1--;
        if(x1<60) r1=1-r1;
      }
      if(r2==0) {
        y1++;
        if(y1>320-60) r2=1-r2;
      }
      else {
        y1--;
        if(y1<60) r2=1-r2;
      }
    }
    // kleine Pause
    for(n=0;n<30000000;n++);
    //-------------------------------
    // 4.) bewegtes Teil Bild aus einem Image
    //-------------------------------
    r1=0;r2=0;
    x1=111;y1=111;
    // Koordinaten (nur ein Teilbild von 100x80 Pixel)
    koord.source_xp=20;
    koord.source_yp=20;
    koord.source_w=100;
    koord.source_h=80;
    koord.dest_xp=x1;
    koord.dest_yp=y1;
    for(n=0;n<5000;n++) {
      UB_Graphic2D_ClearSreenDMA(RGB_COL_GREEN);
      UB_Graphic2D_CopyImgDMA(&Emo2_Image,koord);
      for(m=0;m<500;m++); // pause (sonst flicker)
      UB_LCD_Refresh();
      for(m=0;m<100000;m++); // pause (sonst zu schnell)
      if(r1==0) {
        x1++;
        if(x1>240-101) r1=1-r1;
      }
      else {
        x1--;
        if(x1<2) r1=1-r1;
      }
      if(r2==0) {
        y1++;
        if(y1>320-81) r2=1-r2;
      }
      else {
        y1--;
        if(y1<2) r2=1-r2;
      }
      koord.dest_xp=x1;
      koord.dest_yp=y1;
    }
    //-------------------------------
    // 5.) Ende
    //-------------------------------
    // kleine Pause
    for(n=0;n<30000000;n++);
    // wieder auf Vordergrund schalten
    UB_LCD_SetLayer_2();
    UB_LCD_SetTransparency(255);
   }
}

Hier die Library zum Download :

graphic_dma2d_f429_v101

Hier der komplette CooCox-Projektordner zum Download :

Demo_F429_22


8 Antworten auf 22-Graphic-DMA2D-Library (STM32F429)

  1. Manuel sagt:

    Die Kugel könnte man in Verbindung mit dem Sensor auf der Rückseite kombinieren :)

  2. Fabrice sagt:

    Super Beispiel für DMA2D Speicher zu Speicher kopieren :)
    Jetzt sind paar Sache ein bissen mehr klar ;)

    Gruß.

    Fabrice.

  3. dhampir sagt:

    Moin moin! Zuersteinmal ein großes Lob für die wirklich nützlichen Libs.

    Ich bin gerade dabei ein 24 Bit Display anzusteuern und stelle daher gerade auf ARGB8888 um ( die 16 Bit Variante lief korrekt ), allerdings will mir das noch nicht so ganz gelingen.

    Bisher habe ich
    LCD_FRAME_OFFSET verdoppelt,
    LTDC_Pixelformat_ARGB8888 in UB_LCD_LayerInit_Fullscreen und UB_Graphic2D_ClearScreenDMA gesetzt (hier auch den Farbparameter auf 32 bit geändert und zerlegt in die entsprechenden Felder des InitStructs gelegt),
    UB_LCD_SetCursor2Draw von Byte-Faktor 2 auf 4 gestellt.

    Einige Sachen scheine ich aber zu übersehen, da die Ausgabe statt eines Rechtecks einen recht motiviert rennenenden Pixelbrei ergibt.

    Für einen Hinweis in welchen Ecken ich noch Änderuzngen durchführen muss wäre ich sehr dankbar!

    Achja und bei dieser Lib hat sich ein kleiner Tippfehler eingeschlichen, bei UB_Graphic2D_ClearSreenDMA fehlt ein c :)

    • admin_ub sagt:

      sorry, da kenn ich mich nicht aus

  4. Milas sagt:

    Hallo zusammen,

    gute Arbeit!!!

    Dank der libs konnte ich mich in Rekordtempo mit dem STM32 einarbeiten.

    Ich habe nach den ersten Gehversuchen die einzelnen Hardwarekomponenten ans laufen bekommen inklusive COOS mit Powersave (Sleep und Stop).
    Die Pinbelegung ist am STM32F429Disco mal nicht gerade berauschend (LCD und RAM belegen fast alle AF-Funktionen).
    Daher habe ich statt HW-PWM eine SW-PWM implementiert => ein wenig löten am Board und schon ist die Hintergrundbeleuchtung am Display einstellbar.

    Nun habe ich die LCD_ILI9341-Lib, Graphic2D-Lib und Font-Lib per define auf RGB565, RGB888 und ARGB8888 erweitert. Das Blending für Bachground, Layer1 und Layer2 ermöglicht so im ARGB8888 Mode einfache GUI Programmierung. In RGB565 und RGB888 geht da durch Colorkeying (Transparente Farbe) auch eine ganze Menge.

    Hard-FPU aktiviert, und color konverter geschrieben (HSB to RGB, RGB to HSB, color to RGB, RGB to color, Color Fader)

    Farbkreisdarstellung + Cursor => Fertig ist ein Farbwähler für RGB Lichtquellen.

    + RTC + Teiltransparente Zeiger => coole analog Uhr gleich mit integriert

    + COOS = Speicherverwaltung, Taskmanagement
    + Sleep/Stop/Standby => niedriger Stromverbrauch für Akkubetrieb

    ToDo:
    NRF24 Modul implementierung und fertig ist eine RGB Fernbedienung.
    NRF24 Modul + STM Nucleo Board + FET-Treiber => RGB-Treiber mit niedrigem Standby Stromverbrauch.

    • Cortex-Einsteiger sagt:

      das klingt beeindruckend,
      hast du vor deine Ergebnisse online zu stellen? würde da gerne etwas dran rumprobieren

      mit dem NRF-Modul habe ich schon am STM32 gearbeitet, da gibts fertige Libs im Netz, aber auch so ist die Doku gut und die Module sehr umkompliziert, eine gute Wahl!

  5. Alexis sagt:

    Wie kann ich ein anderes Bild reprroducir Beispiel? Ich habe versucht, die reemplazaer. C, die im Ordner bilder ist, aber es gibt mir Fehler. Danke!


Wie hat Dir dieser Artikel gefallen?

1 Stern2 Sterne3 Sterne4 Sterne5 Sterne (Noch keine Bewertungen)
Loading...

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.