Guten Abend,
Ich habe mal eine Frage. Ich bin zurzeit an einem kleinen Projekt am
basteln für welches ich ein TFT Display gebrauche. Bis jetzt habe ich
immer Displays mit dem ILI9341 Controller genommen meistens in der Größe
von 2,2 oder 2,8 Zoll. Die Display sind mit einem SPI Interface
ausgestattet.
Nun möchte ich gerne ein 4 Zoll Display mit dem ILI9486 Controller
verwenden, aufgrund der besseren Lesbarkeit auf Entfernung wegen der
Größe. Dieser verwendet ein 8-Bit Parallel Datenbus plus ein paar
Steuerleitungen. Da die Controller nahe zu identisch sind war es so gut
wie kein Problem diesen ans laufen zu bekommen. Nur die Geschwindigkeit
ist im Verhältnis zum ILI9341 sehr langsam.
Gut der ILI9486(480x320) hat jetzt doppelt so viele Pixel wie der
9341(320x240). Mit meiner halbwegs "optimierten" ILI9341-SPI Library
schaffe ich bei einem STM32F103C8T6 auf dem SPI2 Bus mit 18MHz SCK Takt
eine vollständige Bildschirmlöschung in 150ms. Was mir schon völlig
ausreicht. Wenn ich den noch schnelleren SPI1 Bus(AHB läuft auf 72MHz)
dann geht das sogar noch schneller bin mir nicht mehr sicher aber das
müsste etwas um die 20-40ms gewesen für eine komplette Löschung. Da kann
man schon fast die einzeln Farben nicht mehr richtig erkennen so schnell
wechselt das ganze.
Beim 4 Zoll Display mit ILI9486 brauche ich für eine komplette Löschung
jedoch 777ms. Selbst wenn ich die Pixelanzahl in der Software begrenze
auf 320x240 so das Links und Unten vom Display nur weiß ist brauche ich
immer noch gut 400ms. Erst bei einer Auflösung von 150x150 komme ich auf
die gleichen 140ms.
Die CPU selbst läuft auf 72 MHz. Der Code für das ganze
Grafik/Ansteuerung Zeugs ist absolut identisch mit dem 9341. Nur der I/O
Kram ist anderes, und da glaube ich ist auch das Problem. Ich verwende
folgenden Code um die Daten ans Display zu senden:
Wüsste jetzt aber nicht wie man das noch groß optimieren kann. Außer das
alle Datenleitungen an einem Port hintereinander zulegen so das LCD_D0 =
PA0 ... LCD_D7 = PA7 wäre. Dann könnte ich das ganze direkt mit
GPIOX->BSRR = xxx machen ohne das ganze if else aber ich weiß nicht ob
das so viel Unterschied machen würde.
Hat da noch jemand ne Idee was man machen könnte um die Übertragung
schneller zu machen? Bzw. warum ist das Display im Parallel Bus so viel
langsamer als das andere im SPI Modus, auch wenn die Pixelanzahl gleich
ist bei beiden.
Die entsprechenden GPIO Pins sind alle als Output Push-Pull mit einer
maximalen Geschwindigkeit von 50MHz konfiguriert.
Mfg
Benutze den FMC. Dann wird alles von der Hardware erledigt, und nur so
erreichst Du die maximale Geschwindigkeit. Für den FMC ist das Display
ein einfaches SRAM.
fchk
Felix N. schrieb:> Dann könnte ich das ganze direkt mit> GPIOX->BSRR = xxx machen ohne das ganze if else aber ich weiß nicht ob> das so viel Unterschied machen würde.
Natürlich macht das einen Unterschied.
Einen Gewaltigen sogar.
Wie oben bereits gesagt: nutze eine MCU mit FMC.
Der F103 hat eh zu wenig RAM für solche Spielereien.
Frank K. schrieb:> Benutze den FMC. Dann wird alles von der Hardware erledigt, und nur so> erreichst Du die maximale Geschwindigkeit. Für den FMC ist das Display> ein einfaches SRAM.
Hallo Frank,
Also ist das FMC so etwas ähnliches wie das XMEM Interface bei den AVRs?
Nur der STM32F103C8T6 hat dieses Interface leider nicht.
Harry L. schrieb:> Natürlich macht das einen Unterschied.> Einen Gewaltigen sogar.
Ok dann habe ich nix gesagt. Wie macht man denn sowas bei den STM32 am
besten? Das BSRR Register hat ja 16-Bit für das setzten eines Bit und 16
Bit für das löschen eines Bits. Kann man dann das Output Data
Register(ODR) nutzen und dann einfach GPIOX->ODR |= data & 0xFF; machen?
Bei dem BSRR Register müsste ich doch wieder abfragen ob es eine 0 oder
1 ist um dann entsprechend das normal Bit zu setzten oder das Bit + 16
zu löschen.
Harry L. schrieb:> nutze eine MCU mit FMC.
Grundsätzlich kein Problem, nur leider sind die tollen MCUs fast einfach
nicht zu bekommen. Ich habe vor einem Monat mit einem Nucleo-64 Board
mit einem STM32F446RE angefangen der hat meinig auch das FMC Interface
andere haben glaubig sogar direkt ein 8080 Parallel Interface. Und die
Blue Pill Board kriegt man ganz gut noch ist zwar meistens ein CKS statt
ein STM drauf, aber für meine letzten 2 Projekte war der völlig
ausreichend.
Harry L. schrieb:> Der F103 hat eh zu wenig RAM für solche Spielereien.
Naa, ich habe das ganze Projekt schonmal auf ein ATMega328P mit 16 MHz
aufgebaut das ging noch nur hat mich die geringe Refresh Rate gestört
und das mir der FLASH ausgegangen ist.
Mfg
Felix N. schrieb:> Außer das> alle Datenleitungen an einem Port hintereinander zulegen so das LCD_D0 => PA0 ... LCD_D7 = PA7 wäre. Dann könnte ich das ganze direkt mit> GPIOX->BSRR = xxx machen ohne das ganze if else
Genau so macht man das!
Felix N. schrieb:> aber ich weiß nicht ob das so viel Unterschied machen würde.
Dann lass dir von mir sagen dass das den ganz grossen
Unterschied macht.
Siehe auch: Beitrag "LCD 480x320 mit wenig Aufwand zum Anbinden"
Mal so ganz blöd gefragt, mir kam da gerade so eine Idee:
Ich habe noch welche von den 74HC595 8-Bit Schieberegistern. Die haben
ja logischerweise 8 Ausgänge(LCD_D0 bis LCD_D7) und entsprechend ein
Shift, Store und Datenpin.
Wenn ich jetzt das SPI Interface nehme MOSI auf den Datenpin des 595
lege. CS auf den Storepin und das SCK Taktsignal auf den Shiftpin dann
dann habe ich doch, in meinen Kopf zu mindestens gerade, ein SPI auf
Parallel Bus Wandler gebaut bzw. das Datenblatt sagt in den
"Applications" sogar auch "Serial to Parallel Data Conversion".
Laut Datenblatt liegt fMax bei 4,5V bei 91 MHz und bei 2V bei 30MHz also
bei 3,3V irgendwo bei ~50MHz oder so. Sollte für 18MHz SPI oder evtl.
auch 36MHz SPI noch locker reichen.
CS, D/C und WR bediene ich dann noch ganz normal über die GPIOs. Müsste
man damit dann nicht auch höhere Geschwindigkeiten erreichen lassen?
Ein versuch wäre es morgen alle mal für mich Wert. Vielleicht gab es
sowas ja auch schon mal? Oder wurde gemacht? Hab mal ein Schaltbild
angehängt wie ich mir das ganze vorstelle.
//EDIT:
Mfg
Arduinoquäler schrieb:> Genau so macht man das!
Ok werde ich als erstes testen bevor ich mein oben Beschriebenes
vorhaben versuche.
Arduinoquäler schrieb:> Dann lass dir von mir sagen dass das den ganz grossen> Unterschied macht.
Ja dann.
Arduinoquäler schrieb:> Siehe auch: Beitrag "LCD 480x320 mit wenig Aufwand zum Anbinden"
Danke
Felix N. schrieb:> Danke
Als Nachtrag:
Arduinoquäler schrieb:> Ich komme damit für den Vorgang des Display Löschens auf nur 90ms Dauer> (480x320 Pixel a 16 Bit).
Auf einem ATMega644 mit 20MHz.
Arduinoquäler schrieb:> Auf einem ATMega644 mit 20MHz.
Ja habe mir den Beitrag gerade auch durchgelesen.
Und das alles nur durch das setzten der Daten auf den Port direkt sprich
GPIO->ODR = data & 0xFF; oder steckt da noch mehr dahinter. Ich meine
der STM läuft ja auf einer ganz anderen Geschwindigkeit.
Hab mir wohl den Code von Arduino Librarys angeschaut wie MCUFriend
allerdings steig ich da nicht hinter da wird das ganze mit Makros
gemacht.
Mfg
Felix N. schrieb:> Müsste> man damit dann nicht auch höhere Geschwindigkeiten erreichen lassen?
Klar geht das auch, denn immerhin kannst du auf dem F103 SPI1
mit 36 MHz laufen lassen (SPI2 nur 18MHz). Da gilt es nur
aufzupassen dass die SPI-Anbindung schon etwas anspruchsvoll
wird (Clock-Flanken, Masse-Bezug etc).
Etwas Overhead gibt es da man bei jedem Byte die SPI-Maschine
des F103 abwarten muss bis sie fertig ist. Das dauert etwas
länger. Beim Parallel-I/O ist man nach dem Write-Low/Write-High
Zyklus und CS-Off schon fertig.
Felix N. schrieb:> Und das alles nur durch das setzten der Daten auf den Port direkt
Ja.
Felix N. schrieb:> oder steckt da noch mehr dahinter
Nein .... Nur CS und Write-Cycle
Felix N. schrieb:> Ich meine> der STM läuft ja auf einer ganz anderen Geschwindigkeit.
Wenn du den F103 meinst, der braucht natürlich auch ein paar
Zyklen, aber das geht trotzdem flott.
Felix N. schrieb:> Hab mir wohl den Code von Arduino Librarys angeschaut wie MCUFriend> allerdings steig ich da nicht hinter da wird das ganze mit Makros> gemacht.
Ich meine: "Arduino Library" sagt alles. Die müssen ja immer
über die Port-Definitionen und Digital Write gehen, das nagt
sehr an der Performance. Seit vielen Jahren für mich als
Geschwindigkeits-Optimierer ein rotes Tuch.
Felix N. schrieb:> isplay mit dem ILI9486 Controller> verwenden, aufgrund der besseren Lesbarkeit auf Entfernung wegen der> Größe. Dieser verwendet ein 8-Bit Parallel Datenbus plus ein paar> Steuerleitungen.
Wie kommst du darauf? Laut Datenbalat Kap. 7.1.3 hat er sowas durchaus.
-
https://www.displayfuture.com/Display/datasheet/controller/ILI9486L.pdf
Dem kompletten Bildschirm löschen (auf einem Controller der weder einen
Doppelten Framebuffer hat noch Blockbefehle) ist meist eh keine allzu
gute Idee. Eher immer nur eine Zeile oder sogar nur einen Bereich
aktualisieren wo sich auch wirklich was geändert hat. Ggf. einfach
nochmal den vorherigen Text mit derselben Farbe wie den Hintergrund
ausgeben und danach den neuen Text in "sichtbarer" Farbe ausgeben. Die
vertikal scroll Funktion ist da manchmal auch recht hilfreich. Eine
Text-Zeile nach unten scrollen und ober dann die neue hinschreiben.
Einfach mal nicht den eingeschlagenen Lösungsweg gedanklich
Festzementieren sondern kreativ werden was noch so alles möglich ist.
Dann kann man selbst mit solch eher einfach gestrickten Controllern ein
ansprechende Anzeige ohne großes Flackern, langsame
Aktualisierungszeiten usw. realisieren.
Vielleicht ein Blackpill(stm32f4) mit externem Flash, da kann man sogar
Zeichensätze als Bilder zum Display schieben. Da Lob ich mir das Arduino
Framework, das gleiche Projekt in einer Stunde auf esp32,atmega oder
Stm32 umbauen und dabei noch Recht leserlicher Code. (Die
Schreibeoutinen für das LCD musste ich bisher immer direkt ohne Arduino
schreiben)
Habe auch schon einen Blackpill liegen um zu testen ob der die
Transparenz beim Schreiben hinbekommt.
> Ich meine der STM läuft ja auf einer ganz anderen Geschwindigkeit.
Irrelevant. Ihr solltest nicht vergessen das bei den modernen MCUs der
Core einen anderen Takt hat als die Peripherie. Da muss runtergetaktet
und einsycronisiert werden.
Ansonsten kann manchmal nicht schaden wenn man in seinem Debugger auf
Assemblerdarstellung umstellt und sich mal den erzeugten Code anschaut.
Sowas bildet ungemein. .-)
Und natuerlich die Finger weg von dem Arduinoscheiss. Wenn da jedesmal
beim rumwedeln mit einem Port noch eine Funktion hinterhaengt dann ist
das toedlch, erst recht bei den lahmen Arms die ihre Register auf dem
Stack sichern muessen und keine Banks umschalten koennen.
Die hier angefuehrte Idee ein Register an SPI zu haengen geht
natuerlich. Das hat man schon vor 30Jahren so gemacht. Ob es
geschwindigkeitsmaessig was bringt muss man sehen oder besser genau
ausrechnen. Ich vermute mal das haengt davon ab ob man das
uebernahme-flag von Hand setzen muss oder ob es von SPI mitgehaendelt
werden kann und man alles vom DMA machen lassen kann.
Olaf
Felix N. schrieb:> Außer das> alle Datenleitungen an einem Port hintereinander zulegen so das LCD_D0 => PA0 ... LCD_D7 = PA7 wäre. Dann könnte ich das ganze direkt mit> GPIOX->BSRR = xxx machen ohne das ganze if else aber ich weiß nicht ob> das so viel Unterschied machen würde.
Zumindest 8 aufeinanderfolgende Portbits, dann kann man das Byte
hinschieben. Daß diese 8-fache if/else Orgie nicht performant ist,
sollte klar sein.
Ich hatte früher auch oft aufs Layout optimiert. Heutzutage sind aber >2
Lagen und Vias kein Kostenfaktor mehr.
Felix N. schrieb:> Grundsätzlich kein Problem, nur leider sind die tollen MCUs fast einfach> nicht zu bekommen.
Da gibt es ein China Board mit dem F407, kostete mal 10€, müsste jetzt
immer noch zu bekommen sein. Das Board das auch in dem STECCY Projekt
hier verwendet wurde. Das hat extra einen Header auf dem 16 Bit für das
FSMC liegen, es gibt auch 320x240 9341 Displays zum aufstecken.
Bei 320x480 hast du den Faktor 153.600, eine Differenz von 1 μs pro
Pixel macht also gleich 153 ms in der Laufzeit. Da lohnt es sich an
dieser Stelle zu optimieren.
Sollte die Lösung übrigens letztendlich in einem preiswerten
SPI-tauglichen TFT-Modul mit 800 x 600 Pixeln liegen, wäre ich sehr
daran interessiert.
Ich finde bei der Auflösung nur die langsamen, Arduino-kompatiblen
8-Bit-Module.
Walter T. schrieb:> Ich finde bei der Auflösung nur die langsamen, Arduino-kompatiblen> 8-Bit-Module.
Dann zeig doch mal dein "TFT-Modul mit 800 x 600 Pixeln" mit 8-Bit
Ansteuerung.
Wenn es um das schnelle Löschen bzw. Füllen eines Bereiches mit einer
Farbe geht, dann kann man das optimieren indem man erst das Window
setzt, dann die Farbe, dann nur noch x*y Schreibtakte. Das aufwändige
zusammenfrickeln des Colorbytes ist da nur einmal nötig.
Libraries wie die AdafruitGFX machen das aber auch so.
Beim übertragen eines Framebuffers hilft das natürlich nicht.
Felix N. schrieb:> //Aus der Header datei> #define DX_HIGH(port, pin) port->BSRR |= (1<<pin)> #define DX_LOW(port, pin) port->BSRR |= (1<<(pin + 16))
(Nebenbemerkung: bisschen schneller geht das auch)
Ein Ver-odern der Bits mit den Registern ist übrigens nicht
erforderlich. Das kann man erkennen wenn man die Funtionen
der SPL (z.B.) anschaut. Es gibt auch ein explizites Reset-
Register für die Port Bits .... spart alles ein paar Zyklen.
Leicht gekürzte Version:
Der Bus wird bitweise angesteuert anstelle von Byteweise.
Weshalb koennen die Bits nicht nebeneinander liegen ? PA0-PA7 ? Weshalb
PB15, PB13, PB12, PA15, PA12, PB4, PB3, PB5 ?
Ich denk das bringt einen Faktor 20. Alle Compares fallen weg und alle
Einzelzugriffe.
Alternativ, die Compares weg mit
PB15 = Data[0] // LSB
data = data shr 1; // shift right 1
PB13 = Data[0]
data = data shr 1; // shift right 1
PB12 = Data[0]
data = data shr 1; // shift right 1
PA15 = Data[0]
data = data shr 1; // shift right 1
PA12 = Data[0]
data = data shr 1; // shift right 1
PB4 = Data[0]
data = data shr 1; // shift right 1
PB3 = Data[0]
data = data shr 1; // shift right 1
PB5 = Data[0]
Vielleicht gibt es auch bitzugriffe...
PB15 = Data[0] // LSB
PB13 = Data[1]
PB12 = Data[2]
PA15 = Data[3]
PA12 = Data[4]
PB4 = Data[5]
PB3 = Data[6]
PB5 = Data[7] // MSB
Purzel H. schrieb:> Weshalb koennen die Bits nicht nebeneinander liegen ?
RTFT (read the fucking thread)
Wenn du nicht blind auf diesen Thread geantwortet sondern
aufmerksam alles durchgelesen hättest würdest du feststellen
dass der TO dies alles schon weiss.
Arduinoquäler schrieb:> Klar geht das auch, denn immerhin kannst du auf dem F103 SPI1> mit 36 MHz laufen lassen (SPI2 nur 18MHz). Da gilt es nur> aufzupassen dass die SPI-Anbindung schon etwas anspruchsvoll> wird (Clock-Flanken, Masse-Bezug etc).
Moin,
Ah ok, ja ich habe es heute versuch ans laufen zu bekommen mit dem 595.
Irgendwie klappt das aber auch noch nicht. Ist aber auch egal ich
bekomme damit scheinbar eh nicht mehr als 222ms hin.
Arduinoquäler schrieb:> Dann lass dir von mir sagen dass das den ganz grossen> Unterschied macht.
Ja und da hattest du recht. Ich habe nun die Pins PA0 bis PA7 für den
Datenbus vorgesehen und konnte die Funktionen auf:
1
GPIOA->ODR = data & 0xFF;
2
WR_ACTIVE;
3
WR_IDLE;
kürzen.
Für eine Vollständige Löschung brauche ich jetzt nur noch 128ms anstatt
700ms. Das ist schon nicht schlecht.
Irgend W. schrieb:> Wie kommst du darauf?
Was meintest du genau?
Irgend W. schrieb:> Eher immer nur eine Zeile oder sogar nur einen Bereich> aktualisieren wo sich auch wirklich was geändert hat.
Das mache ich im normalen Betrieb auch. Nur den Bildschirm komplett zu
löschen ist das zeitintensivste. Wenn das relativ niedrig ist, sind die
Unterfunktionen wie drawRect, fillRect nochmal deutlich schneller. Also
diente die Bildschirmlöschung nur als "Benchmark".
Ich hatte das ganze Projekt wie bereits oben mal erwähnt auf einem
ATMega328P mit 16 MHz aufgebaut. Display war da ein 2,8 Zoll Display mit
dem ILI9341 via SPI angesteuert. Das ganze ist eine Art
"Überwachungsmonitor" für den PC. Die Hardware mit Display und so ist
nur der eine Teil der andere Teil ist meine Java Software welche PC
Daten wie GPU-Auslastung/Temperatur/Takt etc... von GPU-Z einließt und
ans Display sendet und das Display stellt das ganze dann mit Analogen
"Tachoanzeigen" da. Und noch ein bisschen RGB LED Kram.
Das ganze ist also quasi ein "Rework/Überarbeitung ..." oder wie man das
auch immer nennt. Da aber das 2,8 Zoll Display aufgrund der Entfernung
von wo man draufschaut relativ klein ist insbesondere weil ich kleine
Schriftgrößen verwenden musste das ganze jetzt auf einem 4 Zoll Display.
olaf schrieb:> Ansonsten kann manchmal nicht schaden wenn man in seinem Debugger auf> Assemblerdarstellung
Kann ich nicht. Auf dem Blue-Pill Board ist ein CKS32F103C8T6 verbaut
der lässt sich mit dem ST-Link nicht debuggen.
olaf schrieb:> Die hier angefuehrte Idee ein Register an SPI zu haengen geht> natuerlich. Das hat man schon vor 30Jahren so gemacht. Ob es> geschwindigkeitsmaessig was bringt muss man sehen oder besser genau> ausrechnen.
Habe ich noch nicht getestet bzw indirekt. Wenn ich den Code ohne
Display laufen lasse mit den acht Datenleitungen nebeneinander braucht
ein Löschzyklus 128ms(Lass ich mir via USART ausgeben und 1ms Timer),
wenn ich die Lib auf SPI umstellte(SPI1, 36MHz) dann komme ich maximal
auf 222ms Löschzeit für ein Zyklus. Von daher gehe ich mal davon aus das
es langsamer ist als dass 8080 Interface.
Johannes S. schrieb:> Da gibt es ein China Board mit dem F407, kostete mal 10€, müsste jetzt> immer noch zu bekommen sein. Das Board das auch in dem STECCY Projekt> hier verwendet wurde.
Ah danke, schaue ich mir mal an.
Johannes S. schrieb:> Füllen eines Bereiches mit einer> Farbe geht, dann kann man das optimieren indem man erst das Window> setzt, dann die Farbe, dann nur noch x*y Schreibtakte. Das aufwändige> zusammenfrickeln des Colorbytes ist da nur einmal nötig.
Die ili9341_clear Funktion die den ganzen Bildschirm löscht ist
eigentlich eine fillRect Funktionen mit startX und startY = 0 sowie endX
und endY die maximale Pixelanzahl.
Und die fillRect Funktion sieht wie folgt aus:
pushColor sendet einfach 2x ein 8Bit Wert: color >> 8 und color & 0xFF
Purzel H. schrieb:> Weshalb koennen die Bits nicht nebeneinander liegen ? PA0-PA7 ?
Weil das zu dem Zeitpunkt wo ich das Display mit angeschlossen habe die
einzigen freien Pins noch waren da andere Funktionen wie SPI2, I2C1 und
2x USART2 bereits im Betrieb waren.
m.n. schrieb:> Und auch, wenn einzelne Controller nicht verfügbar sind, wäre ein> Nucleo/Discovery-Board eine günstige Lösung, an einen geeigneten µC zu> kommen
Hmm, weiß nicht 20 Euro für ein Nucleo-64 F446RE blechen um an einen
STM32F446RE und an den STM32F103C8T6(Der auf der ST-Link Platine oben
sitzt) Controller zu kommen. Ist glaubig nicht die beste Idee. Zu
mindestens Geldtechnisch gesehen und der Rest der Nucleo Platine ist
dann auch unbrauchbar. Aber als Notlösung denke ich wäre es ok für 1-2
male.
Mfg
Felix N. schrieb:> Irgend W. schrieb:>> Wie kommst du darauf?>> Was meintest du genau?
Warum die nicht auch weiterhin einfach das SPI interface nutzt sondern
meinst jetzt auf einmal als uralte 8080-Interfache nutzen zu müssen?
Felix N. schrieb:> Hmm, weiß nicht 20 Euro für ein Nucleo-64 F446RE blechen um an einen> STM32F446RE und an den STM32F103C8T6(Der auf der ST-Link Platine oben> sitzt) Controller zu kommen. Ist glaubig nicht die beste Idee.
Beim STM32F446RE wird es kaum schneller. Da muss man die Bus-Wartezeiten
TDST und TWC dann tatsächlich implementieren. Für Sie getestet.
Wenn man das Timing zu dicht auf Kante näht, gibt es übrigens leichte
Farbverfälschungen. Irgendwie scheinen die LSB langsamer als der Rest
eingelesen zu werden oder eine höhere Kapazität zu haben, was zu Fehlern
im grünen Bereich führt.
Irgend W. schrieb:> Warum die nicht auch weiterhin einfach das SPI interface nutzt
Die billigen arduinoförmigen Displaymodule sind halt so. SPI wäre glaube
ich jedem lieber. Aber die Module lassen sich nicht ohne weiteres
ändern, da geklebt.
Felix N. schrieb:> und der Rest der Nucleo Platine ist> dann auch unbrauchbar.
Eigentlich kann man von den Nucleos fast nicht zuviele haben. Ich finde
die klasse für jede Art von Testaufbau.
Felix N. schrieb:> Ja und da hattest du recht. Ich habe nun die Pins PA0 bis PA7 für den> Datenbus vorgesehen und konnte die Funktionen auf:> GPIOA->ODR = data & 0xFF;> WR_ACTIVE;> WR_IDLE;>> kürzen.>> Für eine Vollständige Löschung brauche ich jetzt nur noch 128ms anstatt> 700ms. Das ist schon nicht schlecht.
Danke für die Rückmeldung. Meinen Äusserungen entsprechend hättest
du (und ich) ein noch besseres Ergebnis erwartet, aber das kann
man sich nachträglich schon erklären:
- du brauchst ein Read-Modify-Write um den 8-Bit Datenport
zu schreiben. Das braucht mehr Operationen als ein einfaches
direktes Write.
- der F103 hat natürlich eine I/O-Schicht die nicht direkt am
Core hängt was immer zu Synchronisations- bzw. Wartezyklen
führt. Insofern ist ein 8-Bit ATMega von Vorteil bei schnellen
Port Writes.
Will man den ersteren Aspekt vermeiden könnte man versuchen ob
man das ODR auch allein 8-bittig schreiben kann, bin aber
momentan nicht sicher ob das zulässig ist.
Felix N. schrieb:> ili9341_pushColor(color);
Bisschen was kann man noch an Speed gewinnen indem man diese
Funktion nicht aufruft sondern deren Code direkt in die
Schleife legt.
WR_ACTIVE und WR_IDLE hast du nach meinem Hinweis optimiert?
Felix N. schrieb:> wenn ich die Lib auf SPI umstellte(SPI1, 36MHz) dann komme ich maximal> auf 222ms Löschzeit für ein Zyklus.
Ich hatte dir ja weiter oben einen Link gesetzt. Extrem Beispiel mit
overclocking. Ich verwende die gleiche Program Logik aber ohne
overclocking, ist zwar mal eine nette Spielerei aber für einen
vernünftigen Betrieb eh nicht brauchbar. Wie dem auch sei, verwendet man
die SPI mit DMA und baut das Program vernünftig auf dann dauert ein
clear display max 40 mSec. Mit anderen Worten, dein Program gehört mal
aufgeräumt und optimiert.
Felix N. schrieb:> for(y = h; y > 0; y--) {> 11 for(x = w; x > 0; x--) {> 12 ili9341_pushColor(color);> 13 }> 14 }
Da wird unnötig Zeit verbraten. Einmal den Datenport setzen, dann h*w
Pulse mit WR_ACTIVE; WR_IDLE; generieren.
Bernd N. schrieb:> Wie dem auch sei, verwendet man> die SPI mit DMA und baut das Program vernünftig auf dann dauert ein> clear display max 40 mSec.
Das mag für das Setzen von Massen von Bits zutreffen. Es hilft
leider überhaupt nichts für die kleinen Operationen, da wo man
kleine Rechtecke füllen muss. Typisches Beispiel sind Fonts.
Dort müsste man für jeden Teilbereich eines Characters (Quatrate,
Rechtecke oder einzelne Pixel) jeweils einen neuen DMA aufsetzen
was extrem mit Overhead behaftet ist. Nein, man kann nicht
einfach die komplette Bitstruktur eines einzelnen Characters
einfach komplett mit DMA ins Display RAM flashen.
Daher ist DMA in unserem Zusammenhang immer nur die halbe Miete.
Johannes S. schrieb:> Da wird unnötig Zeit verbraten. Einmal den Datenport setzen, dann h*w> Pulse mit WR_ACTIVE; WR_IDLE; generieren.
Ja klar, ganz richtig. Hätte nur auch mal in meinem Code
nachschauen brauchen ....
Arduinoquäler schrieb:> Daher ist DMA in unserem Zusammenhang immer nur die halbe Miete.
Ist bei diesen Displays sinnvoll wenn man erst in einen Buffer zeichnet
und den dann überträgt. Gerade bei Zeichen mit ungleichen Größen kann
man damit flackern vermeiden. Altes Zeichen löschen und neues
drübermalen flackert, auch wenn nur wenige ms dazwischen liegen.
Arduinoquäler schrieb:> Daher ist DMA in unserem Zusammenhang immer nur die halbe Miete.
Nein, das ist ein Baustein von vielen. Ich mache z.B. keine
Grenzwertabfragen in jeder Funktion sondern exakt nur eine an einer
einzigen Stelle.
Das hier ist kraut und Rüben...
Bildschirm löschen ist eine oft vorkommende Aktion, die eine
extra-Implementierung rechtfertigt, um eine große einfarbige Fläche
möglichst schnell zu senden.
Aber der Teil mit den Fonts stimmt natürlich. Hier ist das saubere
Bus-Timing extrem wichtig. Ich habe mal ein Bild angehängt. Ist ein
ILI9341 auf einem STM32F446RE, weil ich das gerade auf dem Schreibtisch
habe, aber beim 9488 sieht es gleich aus. Wegen der Demo habe ich das
Warten ein wenig knapper gemacht.
Der einfarbige dunkle Hintergrund (nicht schwarz) wird mit der immer
gleichen Wiederholung der gleichen zwei Bytes in einer extra dafür
implementierten Funktion möglichst schnell geschrieben und ist
fehlerfrei.
Die Fonts kommen später und werden als Rechtecke geschrieben. Man sieht,
dass einzelne Grünwerte nicht stimmen, obwohl die Einzelpixel sogar
etwas langsamer geschrieben werden. Wenn ganze Spalten gleichfarbig
sind, tritt es nicht oder seltener auf. Der Effekt ist nur bei gekipptem
Display zu sehen.
Bei SPI-Display gibt es diesen Effekt nicht und bei großzügigerem Timing
verschwindet er glücklicherweise. Deswegen reichen einzelne NOPs nicht
mehr auf dem STM32F446 - er kann bei den 8-Bit-Displays nur mit höherer
Taktfrequenz warten.
Johannes S. schrieb:> Ist bei diesen Displays sinnvoll wenn man erst in einen Buffer zeichnet> und den dann überträgt.
Ja gut .... 480x320 Pixel á 16 Bit ergibt gut 300kByte. Um diesen
Buffer bereitzustellen braucht es schon ein etwas grösseres STM32
Kaliber. Nicht aber einen F103.
Mit Framebuffer arbeiten ist daher schon eine andere Liga,
erfordert auch in der gesamten Programmierung ein etwas
anderes Konzept.
Bernd N. schrieb:> Das hier ist kraut und Rüben...
Begründe das bitte ausführlich.
Ich sehe nur ein CS_IDLE welches dort nicht ganz passt.
Und ein ili9341_pushColor(color) welches nur einmal gebraucht
wird (und eben nicht in der Schleife), wie Johannes schon
richtig bemerkte.
Walter T. schrieb:> Die billigen arduinoförmigen Displaymodule sind halt so. SPI wäre glaube> ich jedem lieber. Aber die Module lassen sich nicht ohne weiteres> ändern, da geklebt.
Um deinen Horizont etwas zu erweitern:
Es gibt schon seit vielen Jahren das Display 480x320 mit ILI9488
für den RaspBerry. Das wissen scheinbar nur wenige, oder haben
es nicht kapiert dass es mit SPI geliefert wird, und dass man es
mit wenig Aufwand an jedes STM-Eval-Board oder an einen Arduino
anschliessen kann. Beim Arduino fällt dann noch die Pegel-
Anpassung an 3.3V an.
Siehe z.B. eBay-Artikelnummer 265211449760.
Mittlerweile gibt es auch (von Waveshare) dieses Display mit
SPI und direkt aufsteckbar auf die Arduino-Konnektoren.
Siehe z.B. eBay-Artikelnummer 283705700293.
Wenn sich jemand an ILI9488 vs. ILI9486 aufhängen sollte: die
sind annähernd identisch bzw. gleich zu behandeln.
Arduinoquäler schrieb:> Es gibt schon seit vielen Jahren das Display 480x320 mit ILI9488> für den RaspBerry.
Hier
Beitrag "Re: STM32 F746zg nucleo und ILI9488 TFT per SPI langsam ?"
hatte ich schon mal mit einem Discovery F407 Board geübt.
Ist gut vier Jahre her. Auf dem zweiten Bild sieht man einen
Connector (blau) für die Displays mit 16-Bit Interface
(Ansteuerung über FSMC) und einen weiteren (weiss) für das
"RaspBerry-Display" (Ansteuerung über SPI).
Arduinoquäler schrieb:> Um deinen Horizont etwas zu erweitern:
Es erweitert nicht meinen Horizont, aber es ist gut zu wissen, dass es
diese Module endlich auch in preisgünstig gibt.
Walter T. schrieb:> Es erweitert nicht meinen Horizont
Vielleicht kannst du meinen Horizont erweitern (der ja bereits
sehr gross zu sein scheint) indem du meine offene Frage zu deiner
haltlosen unbegründeten Behauptung beantwortest.
Walter T. schrieb:> mit 800 x 600 Pixeln liegen, wäre ich sehr daran interessiert.>> Ich finde bei der Auflösung nur die langsamen, Arduino-kompatiblen> 8-Bit-Module.
Meine Frage dazu lautete:
Arduinoquäler schrieb:> Dann zeig doch mal dein "TFT-Modul mit 800 x 600 Pixeln" mit 8-Bit> Ansteuerung.
Wenn man schon Zeichnet kann man das Display im 8bit Modus fahren und
kleinere Sachen vom RAM direkt per DMA schreiben.. das müsste definitiv
schneller werden und die kleinen Grafiken kann man sauber anpassen.
Was sagt denn die Berechnung anstatt testen? zum Beispiel 8bit Modus
könnten bis zu 68ms fürs löschen bringen.. mit den 122ms 16bit ist man
da ja sogar unter dem Optimum.
Arduinoquäler schrieb:> Walter T. schrieb:>> mit 800 x 600 Pixeln liegen, wäre ich sehr daran interessiert.>>>> Ich finde bei der Auflösung nur die langsamen, Arduino-kompatiblen>> 8-Bit-Module.
Das war wohl ein freudscher Vertipper.
Walter T. schrieb:> Bildschirm löschen ist eine oft vorkommende Aktion
Ich habe das noch nie gebraucht. Ich überschreibe immer mit dem neuen
Bildinhalt.
Zwischendurch löschen sieht unprofessionell aus, da es flackert, bis man
das neue Bild schreibt. Z.B. bei der Heizungssteuerung fällt das sehr
auf.
Auch bei nem Text-LCD sieht man das schön, wenn Anfänger löschen, bis
der Arzt kommt.
Arduinoquäler schrieb:> Will man den ersteren Aspekt vermeiden könnte man versuchen ob> man das ODR auch allein 8-bittig schreiben kann, bin aber> momentan nicht sicher ob das zulässig ist.
Hallo,
Das Datenblatt vom F103C8T6 sagt beim GPIOX->ODR Register das es nur im
Word Mode adressiert werden darf.
"These bits can be read and written by software and can be accessed in
Word mode only."
Arduinoquäler schrieb:> WR_ACTIVE und WR_IDLE hast du nach meinem Hinweis optimiert?
Ähmm ich habe nochmal geschaut in diesem Beitrag konnte aber nix finden?
Sonst nein da habe ich im Moment noch nix gemacht. Was genau meinst du
mit "optimiert"? Könntest du mir den entsprechend Beitrag nochmal
nennen?
Bernd N. schrieb:> Mit anderen Worten, dein Program gehört mal> aufgeräumt und optimiert.
Ich weiß nicht mehr woher ich genau diese Lib habe. Ursprünglich war sie
für den ILI9341 vorgesehen. Inzwischen habe ich sie für den ILI9341 ein
bisschen optimiert bzw. das habe ich vor 1-2 Jahren gemacht. Ich habe
die Dateien mal angehängt. Nicht wundern warum alles dort mit ili9341
heißt wie gesagt ursprünglich für ili9341 vorgesehen nun auf 8080
Parallel umgeschrieben für ILI9486.
Walter T. schrieb:> Bildschirm löschen ist eine oft vorkommende Aktion, die eine> extra-Implementierung rechtfertigt, um eine große einfarbige Fläche> möglichst schnell zu senden.
Eigentlich mache ich das nur nach dem Init des Displaytreiber und falls
neuzeichen einfach zu aufwendig wäre.
Arduinoquäler schrieb:> Ich sehe nur ein CS_IDLE welches dort nicht ganz passt.
Das passt. Alle Funktionen rufen die ili9341_setAddress Function auf wo
die X und Y Koordinaten gesetzt werden wodrin jetzt gearbeitet wird auf
dem Display und dort mache ich dann das CS_ACTIVE entsprechend mit dem
ganzen DC_COMMAND, DC_DATA etc... und danach kommen ja nur noch Daten
also kommt dann zB. pushColor und danach ist die ganze Kommunikation mit
dem Display abgeschlossen deswegen CS_IDLE. Spart ein paar Takte als
immer wieder CS_ACTIVE; Daten schreiben WR_ACTIVE; WR_IDLE; CS_IDLE.
Arduinoquäler schrieb:> Und ein ili9341_pushColor(color) welches nur einmal gebraucht> wird (und eben nicht in der Schleife)
Das verstehe ich jetzt nicht ganz also die for schleife geht ja die
ganzen Pixel durch die ich füllen will und pushColor sagt welche Farbe
wenn ich die Farbe vorher fest lege was muss ich denn dann in der for
Schleife machen?
Arduinoquäler schrieb:> vielen Jahren das Display 480x320 mit ILI9488> für den RaspBerry. Das wissen scheinbar nur wenige, oder haben> es nicht kapiert dass es mit SPI geliefert wird
Ohh, das hört sich interessant an. SPI ist immer gut, meistens. Und
danke für die Display Links.
Philipp K. schrieb:> RAM direkt per DMA schreiben
Ich muss sagen ich arbeite noch nicht lange mit den STM32 Controllern.
Etwa vor 1,5 Monaten habe ich mit einem Nucleo-64 STM32F446RE
angefangen. Daher kenne ich mich mit den ganzen Bereichen die der
Mikrocontroller bietet noch nicht so gut aus wie zB. bei den AVRs.
Die DMAs machen doch Memory to Memory oder Peripheral to Memory bzw.
umgekehrt. Kann man damit auch die GPIO steuern? Oder bezog sich der DMA
Content auf die Ansteuerung des Displays via SPI?
Philipp K. schrieb:> Was sagt denn die Berechnung anstatt testen?
Muss gestehen das ich keine Ahnung habe was ich da berechnen soll
geschweige denn wie.
Peter D. schrieb:> Ich überschreibe immer mit dem neuen> Bildinhalt.
Wenn das möglich ist mache ich das in der Regel auch. Zum Beispiel habe
ich ein ILI9341 2,8 Zoll Display bei meinem Aquarium Steuergerät verbaut
welches über Menüs verfügt um Werte abzulesen oder einzugeben. Da lösche
ich den Bildschirm komplett einmal wenn das Menü gewechselt wird weil
zum Teil komplette Bereich wie Bearbeitungsknöpfe, Neustart etc.. auf
komplett anderen X,Y Koordinaten gesetzt werden müssen. Änderung im Menü
selbst wie zB. die IP-Adresse des ENC28J60 wird direkt einfach durch ein
neunen String ersetzt da er gleich lang ist überschreibt er einfach den
alten Wert, da flackert dann gar nichts. Sonst wenn die länge nicht mehr
stimmt fülle ich vorher mit einem schwarzen fillRect auf und schreibe
dann neu.
Walter T. schrieb:> Beim STM32F446RE wird es kaum schneller. Da muss man die Bus-Wartezeiten> TDST und TWC dann tatsächlich implementieren. Für Sie getestet.
Ah ok. Auf die TXE Flag zu warten hat funktioniert konnte es aber mit
__NOP() optimieren, anstatt auf das Flag zu warten. Falls sich das "Sie"
auf mich bezogen hat "Du" ist auch okay :)
Walter T. schrieb:> Eigentlich kann man von den Nucleos fast nicht zuviele haben. Ich finde> die klasse für jede Art von Testaufbau.
War heute den ganzen Tag in Essen, zufällig ein Conrad Laden gefunden
hatten aber keine Nucleo Boards mehr sonst hätte ich noch eins von da
mit genommen. Sonst muss ich mal schauen ob ich mir davon noch welche
besorge.
Walter T. schrieb:> Wenn man das Timing zu dicht auf Kante näht, gibt es übrigens leichte> Farbverfälschungen. Irgendwie scheinen die LSB langsamer als der Rest> eingelesen zu werden oder eine höhere Kapazität zu haben, was zu Fehlern> im grünen Bereich führt.
Ja das habe ich beim STM32F103C8T6 mit dem SPI2 Bus der auf 18 MHz SCK
Takt lief auch beobachten können, das es teilweise Probleme gab wenn ich
die Daten ins Datenregister(SPI2->DR) geschoben habe und dann nur 3 NOPs
abgewartet habe. Bei 4 NOPs gehts zur Sicherheit habe ich 5 genommen.
Walter T. schrieb:> Aber die Module lassen sich nicht ohne weiteres> ändern, da geklebt.
Muss man dafür nicht ein paar bestimmte Pins des ILI Controllers auf
Masse bzw. Vcc legen um das Interface festzulegen? Also praktisch fast
unmöglich?
Mfg
Felix N. schrieb:> Die DMAs machen doch Memory to Memory oder Peripheral to Memory bzw.> umgekehrt.
Ja, aber das wichtige ist ja das es ohne rechenticks passiert.. also
quasi ein separater Datenschaufler. Das geht auch zwischen SPI1 und
SPI2.. zum Beispiel schiebe ich die kompletten Bilddaten via dma bei
18Mhz vom Flash ins Display.
Mit Berechnung meinte ich zum Beispiel 1/(18000000/(480*320*8)) für 8
Bit. Wobei ich mich noch Frage ob der stm32 überhaupt 8 Bit kann.
Ich benutze übrigens auch nur den 9488. Kein Plan wieso.
Felix N. schrieb:> Ähmm ich habe nochmal geschaut in diesem Beitrag konnte aber nix finden?> Sonst nein da habe ich im Moment noch nix gemacht. Was genau meinst du> mit "optimiert"?Arduinoquäler schrieb:> Ein Ver-odern der Bits mit den Registern ist übrigens nicht> erforderlich. Das kann man erkennen wenn man die Funtionen> der SPL (z.B.) anschaut. Es gibt auch ein explizites Reset-> Register für die Port Bits .... spart alles ein paar Zyklen.
Johannes S. schrieb:> Wenn es um das schnelle Löschen bzw. Füllen eines Bereiches mit einer> Farbe geht, dann kann man das optimieren indem man erst das Window> setzt, dann die Farbe, dann nur noch x*y Schreibtakte. Das aufwändige> zusammenfrickeln des Colorbytes ist da nur einmal nötig.Felix N. schrieb:> Das verstehe ich jetzt nicht ganz also die for schleife geht ja die> ganzen Pixel durch die ich füllen will und pushColor sagt welche Farbe> wenn ich die Farbe vorher fest lege was muss ich denn dann in der for> Schleife machen?
Gemeint ist dass man den Datenport nur einmal mit der Farbe
beschreibt und dann nur noch Write-low-Write-high Zyklen aus-
führt, so viele wie Pixel geschrieben werden sollen. Das spart
die weiteren Schreibvorgänge auf den Datenport für die immer
gleich bleibende Farbe. Das funktioniert aber nur für 16-Bit-
Datenports, oder Pixel mit 8-Bit Farbauflösung am 8-Bit-Daten-
port, oder mit Nur-Weiss (0xFFFF) oder Nur-Schwarz (0x0000)
oder mit jeder 16-Bit Farbe bei der unteres und oberes Byte
gleich sind.
Alle Klarheiten beseitigt?
Peter D. schrieb:> Ich habe das noch nie gebraucht. Ich überschreibe immer mit dem neuen> Bildinhalt.
Das mache ich innerhalb eines ... nennen wir es "Screens" auch. Aber
beim Screen-Wechsel wird einmal mit der neuen Hintergrundfarbe
überschrieben. Die Kacheln wirklich lückenlos zu bekommen ist mir zu
mühsam.
Felix N. schrieb:> Muss man dafür nicht ein paar bestimmte Pins des ILI Controllers auf> Masse bzw. Vcc legen um das Interface festzulegen? Also praktisch fast> unmöglich?
Genau. Und das auf Flex-Leiter. Ich habe es für mich als "unpraktikabel"
abgestempelt.
> Genau. Und das auf Flex-Leiter. Ich habe es für mich als "unpraktikabel"> abgestempelt.
Das geht schon. Ich hab das vor >15Jahren mal mit einem Display von
Pollin
gemacht weil der Controller auch nur Parallel rausgefuehrt hatte:
http://www.criseis.ruhr.de/bilder/wenn_ihr_euch_dann_besser_fuehlt.jpg
Ich hab das damals sogar ohne Mikroskop gemacht. Der Trick besteht
darin vor den Löten an den duennen Leiterbahnen links und recht einen
Aufkleber drauf zu kleben. Man schafft sich so eine passende
Loetstopmaske .-)
Der rote Faedeldraht ist das uebliche Zeug mit 0.2mm. Das goldene Zeug
ist duenner. Ich glaub das hatte ich irgendwo von einem Trafo
abgewickelt.
Die Loetstellen an dem IC selber sind leider etwas schlecht zu sehen
weil ich das 2k-Kleber draufgemacht habe.
Olaf
Peter D. schrieb:>> Bildschirm löschen ist eine oft vorkommende Aktion>> Ich habe das noch nie gebraucht. Ich überschreibe immer mit dem neuen> Bildinhalt.
Das ist doch praxisfremd. Nach Rückkehr aus einem Untermenü ist der
Bildschirminhalt unbekannt, und es muß zwangsläufig alles gelöscht und
neu geschrieben werden.
> Zwischendurch löschen sieht unprofessionell aus, da es flackert, bis man> das neue Bild schreibt. Z.B. bei der Heizungssteuerung fällt das sehr> auf.
Mit der richtigen Soft-/Hardware flackert da nichts. Aber bei den
"hiesigen" Anwendungen handelt es sich auch wohl mehr um Zeichnen, wo
man dann zusehen kann, wie sich das Bild aufbaut.
Heizungssteuerung? Ist das ein Ersatz fürs Fernsehkucken?
Die kann im Keller doch flackern wie wild.
> Auch bei nem Text-LCD sieht man das schön, wenn Anfänger löschen, bis> der Arzt kommt.
Was soll das denn? Schön, daß man nicht so doof ist wie die Anderen?
Diese ILI-Controller mit ihrer lockeren Anbindung an den µC sind ganz
praktisch, für wenig Geld eine TFT-Anzeige inkl. lokalem Bildspeicher zu
bekommen. Wenn man Geschwindigkeit braucht muß der µC direkten Zugriff
auf den Bildspeicher haben.
Felix N. schrieb:> Hmm, weiß nicht 20 Euro für ein Nucleo-64 F446RE blechen um an einen> STM32F446RE und an den STM32F103C8T6(Der auf der ST-Link Platine oben> sitzt) Controller zu kommen. Ist glaubig nicht die beste Idee. Zu> mindestens Geldtechnisch gesehen und der Rest der Nucleo Platine ist> dann auch unbrauchbar. Aber als Notlösung denke ich wäre es ok für 1-2> male.
Entweder man braucht den µC, dann ist derzeit die Verfügbarkeit das
wichtigste Kriterium, oder man braucht ihn nicht. Bei einem Einzelstück
ist der Preis nicht so entscheidend.
Aktuell werden F303 in angeknabberter Verpackung angeboten:
https://www.mikrocontroller.net/topic/523341#6789705
Leider aber auch ohne FSMC.
olaf schrieb:> Das geht schon. Ich hab das vor >15Jahren mal mit einem Display von> Pollin> gemacht weil der Controller auch nur Parallel rausgefuehrt hatte:>> http://www.criseis.ruhr.de/bilder/wenn_ihr_euch_dann_besser_fuehlt.jpg
Schick! Wild!
m.n. schrieb:> Was soll das denn? Schön, daß man nicht so doof ist wie die Anderen?
Das lese ich nicht daraus. Ich lese daraus lediglich, dass die
Interpretation des vagen Begriffs "häufig" eine andere ist als die, ich
ich in meinem Ursprungs-Post meinte. Ich glaube, den Anfänger-Versuch,
bei jedem Bild-Update bei einem Display ohne Framebuffer erst einmal den
Hintergrund zu löschen, haben wir alle einmal gemacht. Wäre das Ergebnis
gut geworden, wären wir dabei geblieben. Nachdem sich herausgestellt
hat, dass es keine gute Idee ist, machen wir es jetzt anders.
Also meine Aussage von oben etwas defensiver formuliert: Ich halte die
Möglichkeit, den Hintergrund schnell einfarbig zu füllen für wichtig
genug, eine eigene Schreib-Funktion zu rechtfertigen, denn sie
beeinflusst massgeblich die gefühlte Interaktionsgeschwindigkeit
("Schwuppdizität") der grafischen Benutzerschnittstelle (GraBSch) beim
Erstaufbau. Für GraBSchen, bei denen hauptsächlich die gleichen Daten
mit unterschiedlichen Werten dargestellt werden, ist das natürlich
weniger relevant.
Walter T. schrieb:> Ich glaube, den Anfänger-Versuch,> bei jedem Bild-Update bei einem Display ohne Framebuffer erst einmal den> Hintergrund zu löschen, haben wir alle einmal gemacht. Hätte es> geklappt, wären wir dabei geblieben. Nachdem sich herausgestellt hat,> dass es keine gute Idee ist, machen wir es jetzt anders.
Und damit gibt es keinen Grund, einem Anfänger dieses Vorgehen mit "bis
der Arzt kommt" ungefragt vorzuwerfen.
Man muss halt alles selbst machen wenn man viele Wechselnde Bildbereiche
hat. Die Performance benötigt man eigentlich nur für einen Bilderrahmen
oder Seitenwechsel.. da kann man aber Effekte generieren das es wie
gewollt aussieht, zum Beispiel immer im Kreis flitzen und dann in der
Mitte enden, oder umgekehrt.
Bei 18Mhz fängt es ab einer bestimmten Größe an aufzufallen, ich glaube
das war irgendwo bei 100*100Pixel solange man vorher nicht noch
rumrechnen muss.
Welche Library wird denn benutzt?
Ich habe das mal mit dem ili9486 gemacht, das schnellstmögliche mit
Flash sieht man auf dem Video, also das Updates kaum auffallen. Ab
stm32F4 hat man vielleicht noch Platz um sogar ein Hintergrundbild und
Transparenz mit einzubringen, das muss ich aber noch selbst testen, auf
einem esp32 flitzt das richtig Sorglos.
Beispiel mit Flash-Spi..
https://youtu.be/KhNEtgMYAAE
Habe da Mal ein Brekaout gebastelt, das klappt super ohne Transparenz,
dafür ist der F103 einfach zu klein.
https://hackaday.io/project/103344/gallery#cd19b5bfd34ca9a689c9e8de927bc093
Philipp K. schrieb:> Beispiel mit Flash-Spi..> https://youtu.be/KhNEtgMYAAE
Netzfrequenzmessung. Nett.
Wie genau wird der Nulldurchgang ermittelt? Mit Trafo + Komparator oder
Trickschaltung zur Strombegrenzung + Optokoppler?
Jetzt würde mich noch der grafischem Verlauf über die letzten xxx
Minuten interessieren.
Hier gibt es dafür ein nettes Codeschnipsel:
https://www.youtube.com/watch?v=YejRbIKe6e0
Bernd schrieb:> letzten xxx> Minuten interessieren.
Gehört ja eigentlich nicht hierhin.. Ist mit Trafo direkt.. der versorgt
nebenbei noch die Platine selber. und die Anzeige selbst ist schon
mehrfach abgeglichener Live Mittelwert bis es schön Smooth aussah.
Quasi ist das nur TFT Initialisieren, das "Fenster" über die Arduino Lib
setzen und dann mit DMA den Speicherbereich aus dem Flash Hand gecodet
hinschaufeln (Das sind ja nur nen paar Zeilen wenn das init des STM32
stimmt). So direkt mit den Libs hat es nicht geklappt.
m.n. schrieb:> Das ist doch praxisfremd. Nach Rückkehr aus einem Untermenü ist der> Bildschirminhalt unbekannt, und es muß zwangsläufig alles gelöscht und> neu geschrieben werden.
Neu Schreiben reicht völlig und dann bis zum Fensterende mit Leerzeichen
auffüllen. Die Länge des neuen Strings läßt sich ja einfach ermitteln.
m.n. schrieb:> Heizungssteuerung? Ist das ein Ersatz fürs Fernsehkucken?
Das ist das Teil auf dem Heizofen im Keller. Bei jedem Tastendruck
flackert das ganze Display. Aber wenigstens nicht, wenn sich Zahlen
ändern. Hersteller weiß ich nicht.
Bei einem 32Bit-Boliden lege ich einen Bildspeicher im RAM an und
schreibe alle Änderungen dort hinein. Und dann wird der geänderte
Fensterbereich ins Display kopiert.
Peter D. schrieb:> Neu Schreiben reicht völlig und dann bis zum Fensterende mit Leerzeichen> auffüllen. Die Länge des neuen Strings läßt sich ja einfach ermitteln.
Nanu? Warum sollte man ein Grafik-Display ausschließlich wie eine
Text-Konsole nutzen? Oder ist "Fenster" bei Dir eine Kachel
(Fenster/Zelle/wie auch immer ein Rechteck jetzt heißt)?
Philipp K. schrieb:> Ja, aber das wichtige ist ja das es ohne rechenticks passiert.. also> quasi ein separater Datenschaufler.
Hallo, hatte diesen Beitrag im Forum irgendwie ganz vergessen upps ...
Ja ich weiß bzgl. des DMAs hätte ich auch nochmal eine Frage bin mir
nicht sicher ob das so funktioniert wie ich mir das Vorstelle. Da die
STM32 ja deutlich mehr RAM haben als die AVRs zB. F103C8T6 20kB und beim
F446RE schon 128kBytes möchte ich gerne so Art "Grafiken" im RAM
hinterlegen um die dann auf den Display wiederzugeben, zB
Temperaturfühlerzeichen. Bei den AVRs ist das immer am SRAM gescheitert
einmal hatte ich am ATMega2506 ein 56kBytes externes SRAM drangeschraubt
damit ging das ganze dann gut mal abgesehen von der Geschwindigkeit.
Aber egal zur Frage: Ich kann den DMA ja so konfigurieren das die
Quelladresse(Source) auf ein Datenarray zeigt mit den Grafikinhalt und
die Zieladresse(Destination) auf das GPIOA->ODR Register zeigt. Dann
8-Bit Datenmodus etc.. und der DMA würde dann doch die Daten vom Array
auf den GPIOA Port schreiben. Nur kann man den DMA auch sagen das er
zwischen jeden Datenpaket kurz noch was anderes machen soll sprich
WR_ACTIVE; WR_IDLE um auch die Daten auf dem Display dazustellen. Oder
ist der DMA dafür nicht konzipiert?
Arduinoquäler schrieb:>> Ein Ver-odern der Bits mit den Registern ist übrigens nicht>> erforderlich. Das kann man erkennen wenn man die Funtionen>> der SPL (z.B.) anschaut. Es gibt auch ein explizites Reset->> Register für die Port Bits .... spart alles ein paar Zyklen.
Ah danke. Ich habe um die Pins wieder auf LOW zu setzten von BSRR |= (x
+16) auf BRR |= x; geändert. Glaube hat aber nicht wirklich was geändert
ein kompletter Löschvorgang dauert immer noch gute 128ms, wie vorher
auch.
Arduinoquäler schrieb:> Alle Klarheiten beseitigt?
Ja danke für die Erklärung. Ich habe es umgesetzt jetzt weiß ich auch
warum nur die Hälfte vom Bild gelöscht wurde das zweite WR_STROBE fehlte
für das HIGH Byte.
Ich habe die Funktion "ili9341_clearScreenFast(bool white)" genannt.
Damit kann man nur schwarz und weiß löschen im Gegensatz zur
"ili9341_clearScreen" Funktion ist diese 18ms schneller also dauert ein
Löschvorgang 110ms statt 128ms. Optisch konnte ich so gut wie kein
Unterschied feststellen.
Allerdings scheinen Interrupts da auch schon sehr gewaltig sichtbar zu
sein im Display. Ich habe den Timer2 als Overflow Interrupt Event
aktiviert. So das er jede 1ms ein 32 Bit Integer hochzählt("millis")
damit mache ich die Zeitmessung. Wenn ich das ganze runterschraube so
das er jede Mikrosekunde auslöst und dann ein 32 Bit Integer namens
"micros" hochzählt und wenn eine lokale Variable 1000 erreicht "millis"
um eins hochzählt. Kann man die Interrupt Unterbrechungen im Display
sehen. Es sieht so aus als würde es kurz stocken. Evtl. müsste ich den
NVIC während am Display gearbeitet wird deaktivieren und dann wieder
aktivieren, jedoch hätte das auch seine Nachteile dann mal sehen.
Walter T. schrieb:> Genau. Und das auf Flex-Leiter. Ich habe es für mich als "unpraktikabel"> abgestempelt.
Hätte ich schon gemacht wenn ich das nur gesehen hätte wo ich dran
müsste :) Aber wahrscheinlich wäre es mir ein Versuch dennoch wert
gewesen ...
olaf schrieb:> http://www.criseis.ruhr.de/bilder/wenn_ihr_euch_dann_besser_fuehlt.jpg
Nicht schlecht.
m.n. schrieb:> Entweder man braucht den µC, dann ist derzeit die Verfügbarkeit das> wichtigste Kriterium, oder man braucht ihn nicht. Bei einem Einzelstück> ist der Preis nicht so entscheidend.
Natürlich ist der Einzelpreis für mich als Hobbyelektroniker nicht so
entscheidend ich nehme die Dinger ja nicht in 1000x Stück oder so ab.
Nichts desto trotz möchte ich auch nicht unbedingt eine Nucleo Platine
opfern nur um an zwei Chips anzukommen die nicht mal die Hälfte der
Platine kosten. Da nehme ich dann doch die ganze Nucleo Platine und
lasse sie so und integriere sie.
Wobei ich bei reichelt, wo ich hauptsächlich bestelle, gesehen habe das
es dort durchaus noch STM32 Controller gibt welche auch Lieferbar sind
wie zB. der STM32L476VGT6. 1MB Flash, 80MHz und 128kBytes an RAM.
Philipp K. schrieb:> Welche Library wird denn benutzt?
Ich habe meine Treiberlib für den ILI9486 und den GFXlib in einer meiner
Beiträge weiter oben Angehängt. Die GFXlib ähnelt der Adafruit GFX
Library.
Peter D. schrieb:> Neu Schreiben reicht völlig und dann bis zum Fensterende mit Leerzeichen> auffüllen. Die Länge des neuen Strings läßt sich ja einfach ermitteln.
Geht aber auch nur, würde ich jetzt sagen, wenn man das Display als art
"Konsole" nutzt.
Ich habe mal ein Bild von dem Projekt auf dem ATMega328P(Stand 11/2020)
angehängt. Dort sieht man was es am Ende in etwa machen soll wobei ich
dafür jetzt noch mehr Ideen habe als damals. Die maximale
Aktualisierungsgeschwindigkeit für das Display lag irgendwo bei
800-1000ms schneller gings nicht weil das Display einfach solange
braucht. Dort ist es zB. so das wenn der Text von den Stellen gleich
bleibt zB. "330W" und dann kommt "250W" dann wird das einfach direkt als
String überschrieben und es flackert nicht. Wenn das aber von "330W" auf
"80W" wechselt, generiere ich erst dahinter mit fillRect ein schwarzen
Kasten der die 330W vollständig verdeckt und schreibe die 80W dann neu
weil die Position auch wieder angepasst werden muss damit es wieder
mittig ist.
Würde ich das mit dem fillRect nicht machen würde irgendwas von der
alten Zahl stehen bleiben.
Peter D. schrieb:> Bei einem 32Bit-Boliden lege ich einen Bildspeicher im RAM an und> schreibe alle Änderungen dort hinein. Und dann wird der geänderte> Fensterbereich ins Display kopiert.
Wenn ich in diesem Beispiel ein Display mit 480x320 und jeder Pixel ein
16 Bit Farbwert haben kann müsste der Bildspeicher im RAM doch 2.457.600
Bytes(~2,4MB) groß sein oder nicht (480pixel 320pixel 16bit)? Haben
MCUs überhaupt solch riese SRAM Speicher?
Mfg
Felix N. schrieb:> ein Display mit 480x320 und jeder Pixel ein> 16 Bit Farbwert haben kann müsste der Bildspeicher im RAM doch 2.457.600> Bytes(~2,4MB) groß sein oder nicht (480pixel 320pixel 16bit)?
Ich behaupte mal dass meine Rechnung richtig war und ist ...
Arduinoquäler schrieb:> Ja gut .... 480x320 Pixel á 16 Bit ergibt gut 300kByte.
Arduinoquäler schrieb:> Ich behaupte mal dass meine Rechnung richtig war und ist ...
Jop, hab mich vertan. 16 bit sind ja 2 Bytes also mal 2 statt mal 16.
Upps. dann passt das auch mit den 300kBytes. Trotzdem noch viel zu viel
für die meisten MCUs
Mfg
Gibt es schon, ist aber nicht unbedingt nötig. Lvgl hatte ich ja schon
mehrfach erwähnt, da reicht ein Framebuffer von mindestens 10 Zeilen.
Und solche runden Instrumente gibts da auch.
Felix N. schrieb:> Ah danke. Ich habe um die Pins wieder auf LOW zu setzten von BSRR |= (x> +16) auf BRR |= x; geändert.
Dann hast du es immer noch nicht verstanden. Es war das
Ver-odern überflüssig ....
Bei mir ist ein Makro z.B. so definiert:
Arduinoquäler schrieb:> Es war das> Ver-odern überflüssig ....
Okay. Ich wusste nicht das man das Bitschiften(x<<n) Ver-odern nennt.
Arduinoquäler schrieb:> Bei mir ist ein Makro z.B. so definiert:
Ok. Nachdem ich mein WR_PIN von 11 auf (1<<11) geändert habe
funktionierte der neue Makro auch. Das ganze hat massiv Zeit gespart von
128ms auf 68ms bei der normalen Clear Funktionen. Und bei der
"fastClear" von 110ms auf 52ms. Wenn ich das bei den anderen
Steuerleitungen(CS und DC) komme ich auf 66/50ms.
Ich weiß jetzt jedoch nicht was das Steckbrett und die
Steckbrettkabel(~17cm) für ein Einfluss darauf noch haben. Zumal auch
nix abgeschirmt ist oder so am Kabel.
Mfg
Felix N. schrieb:> Okay. Ich wusste nicht das man das Bitschiften(x<<n) Ver-odern nennt.
Nein.
Ver-odern nennt man das wenn man |= anwendet. Mit Shiften
hat das überhaupt nichts zu tun.
Felix N. schrieb:> Nur kann man den DMA auch sagen das er> zwischen jeden Datenpaket kurz noch was anderes machen soll sprich> WR_ACTIVE; WR_IDLE um auch die Daten auf dem Display dazustellen. Oder> ist der DMA dafür nicht konzipiert?
Nein. Dafür bräuchte man den FSMC, der automatisch Schreibimpulse
generiert.
Felix N. schrieb:> Nichts desto trotz möchte ich auch nicht unbedingt eine Nucleo Platine> opfern nur um an zwei Chips anzukommen die nicht mal die Hälfte der> Platine kosten. Da nehme ich dann doch die ganze Nucleo Platine und> lasse sie so und integriere sie.
Würde ich für Einzelstücke auch komplett verwenden, zumal die Bestückung
schon fertig ist.
Felix N. schrieb:> dann passt das auch mit den 300kBytes. Trotzdem noch viel zu viel> für die meisten MCUs
Wenn Du schon bei STM32 bist, dann böte sich ein H750 mit 1 MB RAM an.
Vor einiger Zeit waren die noch für rund 5 € zu bekommen. Zur Zeit sagen
aber alle Preise: kauf mich nicht!
Oder man nimmt eben ein fertiges Board.
Langer Rede wenig Sinn: Du wirst sicherlich bei Deiner jetzigen Lösung
bleiben, ob sie nun schnell oder langsam arbeitet und weil die
Änderungen viel zu arbeitsintensiv wären ;-)
Walter T. schrieb:> Es erweitert nicht meinen Horizont, aber es ist gut zu wissen, dass es> diese Module endlich auch in preisgünstig gibt.
Ich habe mal eines der Module ausprobiert. Die Raspberry-Displays nutzen
gar nicht die SPI-Fähigkeit des ILI9486, sondern haben zwei
74HC4094-Schieberegister an Board und nutzen das 8080-Interface im
16-Bit-Modus. Um einen Tristate-Treiber zu sparen, können Daten nur
geschrieben und nicht gelesen werden. Für einen µC ohne Platz für einen
Framebuffer sind die Dinger damit nahezu unbrauchbar.
Mit den oben beschriebenen Wartezeiten dürften sie auch nicht schneller
als die 8-Bit-8080-Absteuerung sein. Nach dem obigen Frust habe ich
keine Lust auf Benchmarks.
Den Grund für diese merkwürdige Konstruktion verstehe ich nicht. Die
ILI9486 sind ja SPI-fähig und können sogar 3-Leiter-SPI, d.h. es gäbe
keine Kollision mit dem MISO des Touch-Sensors. Bidirektionale
Levelshifter dürften ja auch nicht wirklich teurer als diese merkwürdige
Konstruktion sein.
Schade eigentlich. Es hätte so schön sein können.
Walter T. schrieb:> Schade eigentlich. Es hätte so schön sein können.
Das habe ich bei einigen Lösungen aus Fernost auch schon erlebt.
Wahrscheinlich gibt es dazu auch philosophische Betrachtungen, die
erörtern, warum sich nicht die technische bessere Lösung, sondern nur
das Mittelmaß durchsetzt...
Nachtrag: Nachdem der Anfangsfrust verraucht ist, habe ich doch mal mit
dem "SPI"-Raspberry-TFT etwas genauer hingeschaut:
Wie schon oben geschrieben wird nicht die SPI-Fähigkeit des ILI9486
genutzt, sondern es sind Schieberegister auf dem Modul, und der
Display-IC wird per 16-Bit-8080-Interface angesprochen. Das WR-Signal
("strobe") wird dabei mit einem Zähler aus dem SPI-Clock erzeugt oder
kann wahlweise mit einem Loslassen des Chip-Select-Signals erzwungen
werden.
Die maximale Taktrate, die ich erfolgreich testen konnte, waren etwas
mehr als 20 MHz. Ich habe aber nur jeweils in 2er-Teilungsfaktoren
getestet, weil der SPI-Takt bei üblichen Kachelgrößen ohnehin die
Schreibdauer kaum beeinflusst. (Bei mir sind die Kacheln üblicherweise
32x32 oder 40x40 Pixel.) Wartezeiten sind da wichtiger. Wird die
Wartezeit beim MemoryWriteContinue nicht eingehalten, ergeben sich
falschfarbige Einzelpixel.
Einmal das Display komplett einfarbig füllen geht bei mir in knapp 150
Millisekunden (untere Grenze). Das ließe sich ein wenig optimieren,
indem man das WR-Signal am Schieberegister vorbei von Hand erzeugt, aber
nicht viel. Und bei den üblichen Bitmaps hilft das auch nichts.
Einmal das Display komplett jeden Pixel einzeln mit einem Zufallsmuster
füllen kostet ca. 500 Millisekunden (obere Grenze).
Eine gekachelte Anzeige fühlt sich doch ganz gut an. Aber dass man den
Speicher nicht mehr auslesen kann, nervt natürlich. Einen Hintergrund
einfach "ausgrauen", ohne das Bild komplett neu aufbauen zu müssen, kann
man vergessen. (Das ist mein häufigster Anwendungsfall für
Overlay-Effekte.) Als quasi Drop-In-Ersatz für die bekannten
ILI9341-Module mit SPI-Anschluß ist es damit nicht geeignet.
Also: "Not great, not terrible", wie es so schön heißt.