07-LCD_ILI9341-Library (STM32F429)

diese Library dient zum ansteuern des Grafik LC-Displays auf dem STM32F429-Discovery mit dem ILI9341-Chip. (240 x 320 Pixel und 16bit Farbe)

Das Display hängt am TFT-Controller der CPU und wird im RGB-Mode (mit HSync, VSync und 24bit Farben) betrieben. Der Chip selber wird per SPI-5 angesteuert.
(aus dem Grund wird die SPI-5 Library zusätzlich benötigt)

Als Grafik-RAM wird ein Teil vom externen SD-RAM benutzt
(aus dem Grund wird die SDRAM-Library zusätzlich benötigt)

die Library bedient die Grundfunktionen wie Initialisierung, Screen-Ausrichtung, setzen vom Layer und der Transparenz, setzen vom Cursor und löschen vom Layer.

Für die Textausgabe gibt es eine Font-Library
Für Grafik-Funktionen gibt es eine Grafik-Library

Hinweise zu den Layern :
Das Grafik-RAM ist in zwei Layer unterteil. Layer_1 und Layer_2.
Layer_1 = Hintergrund, Layer_2 = Vordergrund.
Beide Layer haben einen Transparenz Wert [0…255]
Nach dem Init ist die Transparenz von beiden auf 255 aus dem Grund ist nur Layer_2 zu sehen (er verdeckt Layer_1). Man kann in beide Layer Daten schreiben und entweder Layer_1 oder Layer_2 oder beide gemischt darstellen.
Dazu muss zuvor per Funtkion “UB_LCD_SetLayer” der aktive Layer ausgewählt werden in den geschrieben oder dessen Transparenz geändert werden soll.

Hinweise zum Refresh :
Um bewegte Objekte darstellen zu können, wird ein Layer angezeigt und der andere wird aktiviert um Daten aufzunehmen. Wenn das beschreiben vom zweiten Layer fertig ist, reicht es, einmal die Funktion “UB_LCD_Refresh” aufzurufen. Diese tauscht den Layer der angezeigt wird mit dem der die Daten aufnimmt.

BUG Hinweis von “Flo” :
Nach Power-On per USB werden falsche Farben angezeigt.
Workaround : In der Funktion “P_LCD9341_InitChip”
einen LCD-Software Reset einfügen
per “P_LCD9341_CMD(0×01)” und danach eine 7ms Pause.

Benutzte Pins :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
PA3  = B5         PD3  = G7
PA4  = VSYNC      PD6  = B2
PA6  = G2         PD13 = WRX (CMD/DATA)
PA11 = R4         PF7  = SPI_CLK
PA12 = R5         PF8  = SPI_MISO
PB0  = R3         PF9  = SPI_MOSI
PB1  = R6         PF10 = DE (Enable)
PB8  = B6         PG6  = R7
PB9  = B7         PG7  = CLK
PB10 = G4         PG10 = G3
PB11 = G5         PG11 = B3
PC2  = SPI_CS     PG12 = B4
PC6  = HSYNC
PC7  = G6
PC10 = R2

Standard Farben :

1
2
3
4
5
6
7
8
9
10
11
#define  RGB_COL_BLACK          0x0000
#define  RGB_COL_BLUE           0x001F
#define  RGB_COL_GREEN          0x07E0
#define  RGB_COL_RED            0xF800
#define  RGB_COL_WHITE          0xFFFF
 
#define  RGB_COL_CYAN           0x07FF
#define  RGB_COL_MAGENTA        0xF81F
#define  RGB_COL_YELLOW         0xFFE0
 
#define  RGB_COL_GREY           0xF7DE

Funktionen :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ErrorStatus UB_LCD_Init(void);                             // zum init vom Display
void UB_LCD_LayerInit_Fullscreen(void);                    // zum init der Layer
void UB_LCD_SetLayer_1(void);                              // stellt auf Hintergrund Layer
void UB_LCD_SetLayer_2(void);                              // stellt auf Vordergrund Layer
void UB_LCD_FillLayer(uint16_t color);                     // füllt den aktuellen Layer
void UB_LCD_SetTransparency(uint8_t wert);                 // setzt die Transparenz
void UB_LCD_SetCursor2Draw(uint16_t xpos, uint16_t ypos);  // setzt den Cursor
void UB_LCD_DrawPixel(uint16_t color);                     // zeichnet ein Pixel
void UB_LCD_SetMode(LCD_MODE_t mode);                      // Modus : Portrait,Landscape
void UB_LCD_Rotate_0(void);                                // Rotieren um 0 Grad
void UB_LCD_Rotate_180(void);                              // Rotieren um 180 Grad
void UB_LCD_Copy_Layer1_to_Layer2(void);                   // kopiert Inhalt von Hintergrund zum Vordergrund
void UB_LCD_Copy_Layer2_to_Layer1(void);                   // kopiert Inhalt vom Vordergrund zum Hintergrund
void UB_LCD_Refresh(void);                                 // wechselt Layer und zeigt neuen Inhalt an

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
//--------------------------------------------------------------
// File     : main.c
// Datum    : 24.10.2013
// Version  : 1.0
// 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 LCD-Library (ILI9341)
// 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"
 
int main(void)
{
  uint32_t n;
 
  SystemInit(); // Quarz Einstellungen aktivieren
 
  // Init vom LCD
  UB_LCD_Init();
  // Init der Layer
  UB_LCD_LayerInit_Fullscreen();
  // auf Hintergrund schalten
  UB_LCD_SetLayer_1();
  // Hintergrund komplett mit einer Farbe füllen
  UB_LCD_FillLayer(RGB_COL_WHITE);
  // auf Vordergrund schalten
  UB_LCD_SetLayer_2();
  // Vordergrund komplett mit einer Farbe füllen
  UB_LCD_FillLayer(RGB_COL_GREEN);
 
  // Cursor setzen
  UB_LCD_SetCursor2Draw(10,50);
  // einen roten Strich zeichnen
  for(n=0;n<100;n++) {
    UB_LCD_DrawPixel(RGB_COL_RED);
  }
 
  while(1)
  {
 
  }
}

Hier die Library zum Download :

lcd_ili9341_f429_v102

Hier der komplette CooCox-Projektordner zum Download :

Demo_F429_07


25 Antworten auf 07-LCD_ILI9341-Library (STM32F429)

  1. Michael sagt:

    Hallo,
    danke erstmal für deine Arbeit! Ich beginne gerade damit, mich mit Mikrocontrollern zu beschäftigen und deine Librarys und Infos haben den Start erleichtert und beschleunigt.

    Ich hätte eine Frage zu dieser Library:
    Man kann ja den Displayinhalt über Memory Access Control (0×36) drehen und spiegeln, indem man die Scanrichtung über die Bits MV, MX, MX verändert. Das verwendest du auch in UB_LCD_Rotate_0 und UB_LCD_Rotate_180.
    Vielleicht stehe ich gerade auf dem Schlauch, aber wäre es nicht sinnvoll, genau das für den Landscape-Modus zu benutzen (Command 0×36, Data 0×68 oder 0xA8), damit sich das Koordinatensystem nicht verändert – also z.B. 0,0 weiterhin oben links ist, wenn man das Board dreht, anstatt unten links? Ich weiß nicht, ob man dann nicht noch ein paar andere Dinge anpassen müsste (Sync und/oder LCD_COLUMN_ADDR bzw. LCD_PAGE_ADDR etc.), aber ich denke, dass es so möglicherweise “gedacht” ist, damit man nur initialisieren muss und der Rest mehr oder weniger von selbst passiert.
    Falls das kein völliger Unsinn ist (wie gesagt, ich bin Anfänger …), wäre es toll, wenn du dir das mal ansehen könntest.

    • admin_ub sagt:

      ja…dann probier das mal und sag bescheid wie es geht…ich habs nicht geschafft. Das Display wird im RGB-Mode angesteuert (mit HSync,VSync) und in dem Mode scheint es IMMER zuerst die Horizontale (kleine) Bildseite zu zeichnen, egal was man in die Register schreibt.

  2. Michael sagt:

    Schade, aber wenn es nicht geht, geht’s eben nicht. Scheint wohl an der Art der Ansteuerung zu liegen. Man kann das Bild drehen, aber dann fehlt auf der langen Seite ein 80 Pixel breiter Streifen (eben 320 – 240). Diesen bekomme ich breiter, aber nie schmaler als 80 Pixel oder gar ganz weg. Habe so etwas inzwischen auch im Mikrocontroller-Forum und auf my.st.com gelesen.

  3. Oliver sagt:

    Hallo,
    tolle webseite.
    Habe eine Anwendung in der das externe RAM sinnvoll wäre aber das display zweitrangig ist, zumindest nicht die schnelle Ansteuerung nötig ist bzw. das display besser separat vom board. Ist es möglich/sinnvoll die Display Pins anders zu nutzen bzw. welche Pins bleiben trotzdem nicht nutzbar und müssen auf high oder low gesetzt werden. Kenn mich nicht so aus, aber könnte mir z.B. vorstellen wenn ich das display im Dauerreset halte, dass dann die uC pins nutzbar sind (brauche insgesamt 16 inputs + 16 outputs). Die meinsten Pins sind ja bei diesem Demo board schon vorbelegt…
    Wenn jemand das auf die schnelle überblickt würde ich mich über einen Tipp freuen.
    Danke.

    • admin_ub sagt:

      wenn du das Display gar nicht brauchst, kannst du es auch komplett vom Eval-Board runterlöten. Das hat “Vampire” gemacht und dann einen VGA-Monitor angeschlossen. Hier ist die Pinbelegung zu finden : http://mikrocontroller.bplaced.net/wordpress/?page_id=2848
      Es müssen keine Pins der CPU auf irgendwelche festen Signale gelegt werden.

  4. Frank sagt:

    Könnte man eigentlich auch per DMA auf einem Layer bzw. zwischen den beiden Layern alles oder Bereiche kopieren? Also so ähnlich wie mit UB_Graphic2D_CopyImgDMA in der 22-Graphic-DMA2D-Library, aber mit einem der Layer als Quelle?

    • admin_ub sagt:

      klar, dem DMA ist egal woher er die Daten holt. Die Source-Adresse muss dann halt eine aus dem externen SD-RAM sein. Ich hab hier ein Beispiel das einen kompletten Screen (320×240) vom SD-RAM in einen anderen Bereich kopiert. (aus dem Oszi-Projekt)

      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
      
      uint32_t LCD_MenuFrameBuffer=LCD_FRAME_BUFFER + (2*LCD_FRAME_OFFSET);
      uint32_t LCD_ADCFrameBuffer=LCD_FRAME_BUFFER + (3*LCD_FRAME_OFFSET);
       
      void UB_Graphic2D_Copy1DMA(void)
      {
        DMA2D_InitTypeDef      DMA2D_InitStruct;
        DMA2D_FG_InitTypeDef   DMA2D_FG_InitStruct;
       
        uint32_t  dest_address = 0;
        uint32_t  source_address1 = 0;
       
        // Ziel Adresse im Display RAM
        dest_address = LCD_CurrentFrameBuffer;
       
        // Quell Adresse vom ADC
        source_address1  = LCD_ADCFrameBuffer;
       
        DMA2D_DeInit();
        DMA2D_InitStruct.DMA2D_Mode = DMA2D_M2M;
        DMA2D_InitStruct.DMA2D_CMode = DMA2D_RGB565;
        DMA2D_InitStruct.DMA2D_OutputMemoryAdd = dest_address;
        DMA2D_InitStruct.DMA2D_OutputGreen = 0;
        DMA2D_InitStruct.DMA2D_OutputBlue = 0;
        DMA2D_InitStruct.DMA2D_OutputRed = 0;
        DMA2D_InitStruct.DMA2D_OutputAlpha = 0;
        DMA2D_InitStruct.DMA2D_OutputOffset = 0;
        DMA2D_InitStruct.DMA2D_NumberOfLine = LCD_MAXY;
        DMA2D_InitStruct.DMA2D_PixelPerLine = LCD_MAXX;
        DMA2D_Init(&DMA2D_InitStruct);
       
        DMA2D_FG_StructInit(&DMA2D_FG_InitStruct);
        DMA2D_FG_InitStruct.DMA2D_FGMA = source_address1;
        DMA2D_FG_InitStruct.DMA2D_FGCM = CM_RGB565;
        DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_MODE = NO_MODIF_ALPHA_VALUE;
        DMA2D_FG_InitStruct.DMA2D_FGPFC_ALPHA_VALUE = 0;
        DMA2D_FG_InitStruct.DMA2D_FGO=0;
        DMA2D_FGConfig(&DMA2D_FG_InitStruct);
       
        DMA2D_StartTransfer();
       
        while(DMA2D_GetFlagStatus(DMA2D_FLAG_TC) == RESET);
      }

      • Frank sagt:

        Super, danke! Das ist sehr nützlich. Ich hatte befürchtet, dass es dabei irgendwelche Einschränkungen gibt.

  5. Tamer SAFAK sagt:

    Hi Uwe, is it possible to use other than spi5? Because I need to use 16 channels ADC.

    Thanks,

    • admin_ub sagt:

      The connection of the LCD on the STM32F429i-Disco-Board is fix. You cant change it without removing the complete display. Also you have not enough free ADC-Pins, only 4 are available (have a look on the pinout : http://mikrocontroller.bplaced.net/wordpress/wp-content/uploads/2013/10/Pinbelegung_f429_v100.html)

      • Tamer SAFAK sagt:

        I’ll design a new board with 4.3″-7″ tft lcd. So, how should I use the pins configuration for 16 channels adc? I am wating your advise.

        • admin_ub sagt:

          in a “new” design you are free to choose any SPI-Channel you want. But you can also add a 16-to-1 analog Multiplexer, in this case you only need one free ADC-Channel.

  6. Helmut sagt:

    a little bit Fehler oben in der Pin-Liste:
    PA3 = B5

    Gruß Helmut

    • admin_ub sagt:

      danke, ist auch im Source-File falsch !

  7. Flo sagt:

    Bei mir waren nach einem Power-on durch Stecken des USB-Kabels am STM32F429I-DISCO immer die Farben invertiert. Erst nach Reset durch Flashen oder den Reset-Button waren die Farben richtig.

    In P_LCD9341_InitChip habe ich ganz am Anfang ein P_LCD9341_CMD (0×01) gefolgt von 7 ms Wartezeit eingebaut (5 ms reichen laut Datenblatt, aber man weiß ja nie). Das macht einen Software-Reset des LCD-Controllers und dann stimmen auch beim Kaltstart die Farben.

    • admin_ub sagt:

      Danke, habe den Hinweis als “BUG” vermerkt.

  8. Lohmann sagt:

    Wie kann ich das LCD in ein absolut leeres Projekt einbinden also nur
    die main.h mit noch nichts inizialisiert wie gehe ich da vor?

    • admin_ub sagt:

      Das Projekt von hier “Demo_07″ ist doch absolut leer. Weniger geht nicht. was du machen kannst, ist alles innerhalb der Main.c löschen…aber dann fehlt dir die Initialisierung vom LCD !!!

  9. Chaoskind sagt:

    MoinMoin,

    ich hab mich auch mal an der Libary fürs Display auf dem STM32F429 Disco Board befasst, und wie Flo auch festgestellt, dass das Display nach PowerOn “rumspinnt”.
    Jedoch wirft das Workaround bei mir nen Fehler:

    [cc] C:\Users\Ichich\Desktop\ub_lib\font\ub_lib\stm32_ub_lcd_ili9341.c: In function ‘P_LCD9341_InitChip’:
    [cc] C:\Users\Ichich\Desktop\ub_lib\font\ub_lib\stm32_ub_lcd_ili9341.c:526:3: error: stray ‘\327′ in program
    [cc] P_LCD9341_CMD(0×01);
    [cc] ^
    [cc] C:\Users\Ichich\Desktop\ub_lib\font\ub_lib\stm32_ub_lcd_ili9341.c:526:19: error: expected ‘)’ before numeric constant
    [cc] P_LCD9341_CMD(0×01);
    [cc] ^
    [cc] C:\Users\Ichich\Desktop\ub_lib\font\ub_lib\stm32_ub_lcd_ili9341.c:525:12: warning: unused variable ‘i’ [-Wunused-variable]
    [cc] uint32_t i;
    [cc] ^

    Scheinbar wird P_LCD9341_CMD(0×01) nirgendwo definiert. Könntest du mir sagen, wie und wo ich was definieren muss, damit das Softreset vom LCD klappt?

    Vielen Dank im vorraus und mit freundlichen Grüßen
    Chaos

    • admin_ub sagt:

      dein Fehler muss woanders liegen (die Zeile stimmt). Starte nochmal mit dem laufenden Projekt von hier und füge folgendes in die “P_LCD9341_InitChip” per Copy&Paste ein

      void P_LCD9341_InitChip(void)
      {
        P_LCD9341_CMD(0x01);          // reset
        P_LCD9341_Delay(500000);   // pause
        // ...
      }
      
      
      

  10. Chaoskind sagt:

    Danke für die Antwort, ich hab meinen Fehler inzwischen gefunden. Ich hatte wohl in der falschen Reihenfolge includiert. Nachdem ich nun als erstes die stm32f4xx.h einbinde, klappt alles problemlos.

    Noch viel mehr Dank als für die Antwort, gebührt dir für deine Libs, sie funktionieren, nachdem man eigene Fehler ausgemerzt hat, tadellos.

    Ein kleiner Tipp, der meiner Meinung nach die Farbwahl erleichtert:


    uint8_t Rot, Gruen, Blau;//Rot 0-31, Gruen 0-63, Blau 0-31
    uint16_t Farbe;

    Farbe = (Rot << RGB_R) | (Gruen << RGB_G) | (Blau << RGB_B);
    UB_LCD_DrawPixel(Farbe);

    MfG Chaos

  11. Chaoskind sagt:

    P.S.

    Ich hab die entsprechenden defines vergessen, hier nochmal die richtige Version:

    #define RGB_R 11
    #define RGB_G 5
    #define RGB_B 0

    uint8_t Rot, Gruen, Blau; //Rot 0-31, Gruen 0-63, Blau 0-31
    uint16_t Farbe;

    Farbe = (Rot << RGB_R) | (Gruen << RGB_G) | (Blau << RGB_B);
    UB_LCD_DrawPixel(Farbe);

  12. Chaoskind sagt:

    Ist es eigentlich auch möglich, den 18Bit-Farbmodus mit deiner Lib zu starten? Bzw kannst du mir auf die Schnelle sagen, was ich da umschreiben müsste?

    Mit Dank und freundlichen Grüßen im Voraus,
    Chaos

    • admin_ub sagt:

      da musst du im Datenblatt vom Display nachlesen.

  13. Max sagt:

    Hallo
    ist es auch möglich, das Display ohne den SDRAM zu nutzen? Kann man in deiner Lib den SDRAM deaktivieren?

    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.