Beim Setzen von Pixel werden 2 statt 1 gesetzt (STM32F4 + ili9341))

OP #5980879
Lesenswert?

Hallo,

ich sammle gerade meine erste ersten Erfahrungen mit Mikrocontrollern 
und habe mir dafür das Board STM32 F4 Discovery Board 29zit ausgesucht. 
Als Programmiersprache verwende ich C++.

Mein Ziel ist es Bilder und Animationen auf dem auf dem Board verbauten 
Display anzuzeigen. Aktuell habe ich das Problem, dass meine Funktion 
drawPixel(int const x, int const y, int const color) zwei statt einem 
Pixel zeichnet.

Mein allgemeines Vorgehen:
- SDRAM initalisiert
- SPI initialisiert (Für die Ili9341 InitSequence)
- Ili9341 initialisiert
- LTDC initalisiert
- Layer 1 von 2 erstellt mit der Abmessung des Displays
- Funktion zum Setzten eines Pixels

Mein Code:
1
  
2
  static constexpr int const width = 240U;
3
  static constexpr int const height = 320U; 
4

5
  static constexpr int const hSync = 10;               
6
  static constexpr int const vSync =  2;        
7
  static constexpr int const horBackPorch = 20;
8
  static constexpr int const verBackPorch =  2;
9
  static constexpr int const horFrntPorch = 10;
10
  static constexpr int const verFrntPorch =  4;  
11
  static constexpr unsigned const horTotal = hSync + horBackPorch + width  + horFrntPorch;
12
  static constexpr unsigned const verTotal = vSync + verBackPorch + height + verFrntPorch;
13
  
14
  //Setze Display-Maße
15
  ltdc.SSCR = ((hSync - 1) << INDX_LTDC_SSCR_HSW) | ((vSync - 1) << INDX_LTDC_SSCR_VSH);  
16
  ltdc.BPCR = ((hSync + horBackPorch - 1) << INDX_LTDC_BPCR_AHBP) | ((vSync + verBackPorch - 1) << INDX_LTDC_BPCR_AVBP);
17
  ltdc.AWCR = ((hSync + horBackPorch + width - 1) << INDX_LTDC_AWCR_AAW) | ((vSync + verBackPorch + height - 1) << INDX_LTDC_AWCR_AAH);
18
  ltdc.TWCR = ((verTotal - 1) << INDX_LTDC_TWCR_TOTALH) | ((horTotal - 1) << INDX_LTDC_TWCR_TOTALW);
19
  
20
  //Hintergrundfarbe Schwarz
21
  ltdc.BCCR = (0x000000);
22
  
23
  //Aktiviere Imitiate Reload
24
  ltdc.SRCR |= MASK_LTDC_SRCR_IMR;
25
  
26
  //Setze FrameBuffer (externer SDRAM)
27
  layer.CFBAR = 0xD0000000; 
28
  layer.CFBLR |= (width * 2) << 16 | (width * 2 + 3); //*2 = PixelSize von RGB565
29
  layer.CFBLNR |= height;
30
  
31
  //Setze Pixelformat
32
  layer.PFCR |= MASK_LTDC_Lx_PFCR_RGB565;
33
  
34
  //Setze Transparenz (Keine)
35
  layer.CACR = 255; 
36
  
37
  //Setze Layergröße auf Displaygröße
38
  layer.WHPCR = hSync+horBackPorch+width-1 << INDX_LTDC_Lx_WHPCR_WHSPPOS | hSync+horBackPorch;  
39
  layer.WVPCR = vSync+verBackPorch+height-1 << INDX_LTDC_Lx_WVPCR_WVSPPOS | vSync+verBackPorch;
40
  
41
  //Aktiviere die erste Layer
42
  layer.CR |= MASK_LTDC_Lx_CR_LEN; 
43
  
44
  //Aktiviere den LTDC
45
  ltdc.GCR |= MASK_LTDC_GCR_LTDCEN;
46
  
47
  //Setze den ersten Pixel des Displays weiß.
48
  int x = 0;
49
  int y = 0;
50
  *((uint32_t *) 0xD0000000 + (x + y * width)) = 0xFFFF;
51
  //Resultat: Die ersten 2 Pixel sind weiß. Unabhängig vom x und y werden immer zwei Pixel gesetzt.

Ich kann an jede Stelle des Displays einen Pixel setzen, allerdings wird 
der Pixel rechts daneben auch gesetzt. Habe ich evtl etwas falsch 
konfiguriert?

Ich hoffe mir kann jemand helfen, ich bin am verzweifeln :-).
Gast #5980977
Lesenswert?

> hänge doch bitte den gesamten Code als Attachment an.

Ausserdem sollte der Code natuerlich funktionieren und
ordentlich dokumentiert sein.
Nicht funktionierenden Code braucht kein Mensch.
OP #5981993
Lesenswert?

Hallo, danke für eure Antworten.
Ich habe tatsächlich einen uint32_t-Wert als Color verwendet statt einen 
uint16_t allerdings hat das bei mir keine Auswirkung auf die Darstellung 
gehabt.
1
 *((uint32_t *) 0xD0000000 + (x + y * width)) = 0xFFFF;

Das uint32_t hier bezieht sich auf die Speicheradresse.


Ich weiß immer noch nicht, weshalb 2 statt ein Pixel gezeichnet werden 
und habe deshalb meinen Code angehängt. Allerdings glaube ich, dass oben 
schon alle Konfigurationen, die das Zeichnen des Pixels beeinflüssen 
können, zu sehen sind.

- LTDC Konfiguration
- Layer Konfiguration
- Zeichnen-Funktion



Viele Grüße

Matthias
Angehängte Dateien:
Gast #5982005
Lesenswert?

Mächtiger M. schrieb:
> *((uint32_t *) 0xD0000000 + (x + y * width)) = 0xFFFF;
>
> Das uint32_t hier bezieht sich auf die Speicheradresse.

Nö, das uint32_t bezieht sich auf die Speichestelle wo Deine Adresse 
hinzeigt. Oder anders gesagt: Du schreibst immer noch mit 32 Bit.
Und vermutlich am Ende auch deutlich über Deinen Framebuffer hinaus.
(Firma: fritzler-avr.de) #5982041
Lesenswert?

Das braucht so viel Speicherplatz wie dein Framebuffer jetzt auch.
Meinste den Framebuffer gibts kostenlos?

Wenn du aber nicht weist was ein Linkerscript ist kann das eine schwere 
geburt werden.
Makefile und Linkerscript sind übrigens nicht in deinem zip vorhanden.
Gast #5982042
Lesenswert?

guest schrieb:
> Nö, das uint32_t bezieht sich auf die Speichestelle wo Deine Adresse
> hinzeigt. .......

Leuchtet mir als Mitlesender noch nicht ganz ein.

Für einen Schreibvorgang 32 Bit erzeugt der FMC ja nur einen
Write Strobe. Da das Display einen 16-Bit Port hat kann es doch
eigentlich auch nur 16 Bit (also ein Pixel-Wort) durch einen
Write Zyklus bekommen.

Wenn zwei Pixel geschrieben werden braucht es einen weiteren
Write Strobe. Wo soll der herkommen? Das zweite Pixel des
Diaplays liegt ja auf den oberen 16 Bit der ersten Adresse
des STM Adressraums.

Oh ich glaube es wird mir klar: da der FMC nur 16 Bit breit
ist schreibt ein 32 Bit Zugriff tatsächlich 2 mal hinter-
einander und generiert daurch zwei Write Strobes.

Der Gedanke kommt beim Schreiben ... oder so ähnlich heisst
das Sprichwort.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren