Forum: Mikrocontroller und Digitale Elektronik rechenzeit dot-matrix-display


von M. M. (blackcow)


Lesenswert?

hallo!

was habt ihr für erfahrung mit rechenzeit von 8-bitter in verbindung mit 
grafik-lcds? das ding ist: ich hab an meinem atmega328 ein lcd mit 
122x32 pixel drangeklatscht. es gibt ein menü. in den einzelnen menüs 
werden bis jetzt nur grafic-primitives like lines, points und rechtecke 
gezeichnet. außerdem werden asci-zeichen dargestellt. für einen screen 
braucht er (20MHz takt) so um die 35ms. d.h. ca. 120 befehle pro pixel, 
bzw. 700000 befehle pro screen. ist das normal? wie lange dauert das bei 
euren projekten? kann das noch spürbar verbessert werden (ich hab das 
ganze projekt selbst programmiert, deswegen wollte ich mal wissen wies 
im groben so aussieht mit der effizienz).

von Bernd (Gast)


Lesenswert?

Deine Tastatur ist defekt. Es kommen nur Kleinbuchstaben.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

M. M. schrieb:
> für einen screen braucht er (20MHz takt) so um die 35ms.

Und? Ist das ein Problem?

Welche Aufgabe hat das Display? Soll es für eine Benutzerschnittstelle 
da sein, d.h. auf Benutzereingaben reagieren und irgendwelche Werte 
anzeigen?

Welche Aktualisierungsrate meinst Du denn, in so einem Fall zu 
benötigen?

von M. M. (blackcow)


Lesenswert?

Rufus Τ. F. schrieb:
> M. M. schrieb:
>> für einen screen braucht er (20MHz takt) so um die 35ms.
>
> Und? Ist das ein Problem?
>
> Welche Aufgabe hat das Display? Soll es für eine Benutzerschnittstelle
> da sein, d.h. auf Benutzereingaben reagieren und irgendwelche Werte
> anzeigen?
>
> Welche Aktualisierungsrate meinst Du denn, in so einem Fall zu
> benötigen?

Nachdem ich die Tastatur jetzt repariert habe: Die Aktualisierungsrate 
reicht ja mit 10 Bildern/Sekunde dicke bei einem LCD. Mich interessiert 
einfach nur die Effizienz meines Codes.

von Rudolph R. (rudolph)


Lesenswert?

Kommt darauf an, wie das Display arbeitet.
Ich habe aus einem DOGXL160 quasi ein Text-Display mit 20x13 Zeichen 
gemacht.

https://www.mikrocontroller.net/attachment/212667/DSC00245.JPG

Das ist eine Weile her aber ich meine mich zu erinnern, dass aleine 28 
SPI Übertragungen notwendig waren um ein einzelnes Zeichen zu malen.
Das kam daher das für jeden Pixel zwei Bit zu senden waren.
Dazu kam noch die Daten für jedes Zeichen aus dem Zeichensatz im FLASH 
auszurechnen.

von Frank (Gast)


Lesenswert?

M. M. schrieb:
> Mich interessiert einfach nur die Effizienz meines Codes.

Wie kann das jemand beurteilen wenn du ihn nicht angehängt hast?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

M. M. schrieb:
> Mich interessiert einfach nur die Effizienz meines Codes.

Das Pinseln einzelner Pixel ist langsamer als das Übertragen kompletter 
Bytes. Das Berücksichtigen des bereits vorhandenen Bildschirminhalts ist 
langsamer als das Überschreiben.

Sofern Dein µC ausreichend Speicher hat, kann es sogar effizienter sein, 
ein komplettes Abbild des Bildschirminhalts im Speicher vorzuhalten und 
den nach Änderungen per DMA auf das Display auszugeben.
Dein Display ist 122x32 Pixel = 488 Byte groß und Dein Atmega 328 hat 2 
kByte RAM (aber anscheinend kein DMA).

Je nachdem, wie das Display anzusteuern ist, kann es effektiver sein, 
nach jeder Änderung des Inhaltes komplette 488 Bytes zu übertragen (wenn 
der Displaycontroller ein sequentielles Beschreiben mit automatischem 
Inkrementieren des Adressregisters unterstützt).

Auch ohne DMA sollte das in einer einfachen Schleife recht flott gehen.

Was für ein Display (mit was für einem Controller) verwendest Du und wie 
ist das angeschlossen?

von B e r n d W. (smiley46)


Lesenswert?

> ein komplettes Abbild des Bildschirminhalts im Speicher vorzuhalten

Volle Zustimmung, es wird eine Funktion benötigt, welche den Buffer ins 
Display schiebt. Falls sich die Display-Routinen die niedrigste und die 
höchste veränderte Adresse seit dem letzten Copy-Befehl merken, kann man 
unter Umständen die Ausführung von Curser/Menüs nochmal deutlich 
beschleunigen.

von Möglichkeit (Gast)


Lesenswert?

Wenn man kein DMA hat hilft auch folgender Programmaufbau.
Das Hauptprogramm besteht aus einer kurzen Schleife, die nichts anderes 
tut als so schnell wie möglich den Bildinhalt zyklisch vom internen RAM 
zum Display zu übertragen.
Alle anderen Funktionen und Berechnungen werden komplett in einem 
Timer-Interrupt abgearbeitet.
Vorteil ist, die Bildausgabe behindert niemals die Berechnungsarbeit 
oder das Tastenhandling. Sie wird nur langsamer wenn der Controller viel 
rechnen muss.

von M. M. (blackcow)


Lesenswert?

Rufus Τ. F. schrieb:
> Sofern Dein µC ausreichend Speicher hat, kann es sogar effizienter sein,
> ein komplettes Abbild des Bildschirminhalts im Speicher vorzuhalten und
> den nach Änderungen per DMA auf das Display auszugeben.
> Dein Display ist 122x32 Pixel = 488 Byte groß und Dein Atmega 328 hat 2
> kByte RAM (aber anscheinend kein DMA).
>
> Je nachdem, wie das Display anzusteuern ist, kann es effektiver sein,
> nach jeder Änderung des Inhaltes komplette 488 Bytes zu übertragen (wenn
> der Displaycontroller ein sequentielles Beschreiben mit automatischem
> Inkrementieren des Adressregisters unterstützt).
>
> Auch ohne DMA sollte das in einer einfachen Schleife recht flott gehen.
>
> Was für ein Display (mit was für einem Controller) verwendest Du und wie
> ist das angeschlossen?

Also, die Daten kommen per 8 Bit breitem Interface in den 
LCD-Controller. Das Display ist in 4 horizontale "Pages" aufgeteilt. 
Wenn ich nun eine Page übertragen möchte, so addressiere ich zuerst die 
Page, leg dann dein Byte an und gebe einen Bestätigungsflanke aufs 
clk-Signal. Der Controller inkrementiert dann die X-Koordinate. Die 
übertragung geht so sehr schnell.

Ich hab in meinem Controller den Displayinhalt in einem Array im SRAM 
gespeichert. Dann hab ich außerdem noch ein Pointer-Array, in dem die 
jeweiligen Funktionen adressiert sind, die ein bestimmtes Fenster im 
Display-Array erzeugen. Nachdem eine solche Funktion aufgerufen wurde, 
wird das gesamte Display-Array ausgegeben.

Was mich aber hauptsächlich interessiert ist die Berechnungszeit des 
Inhalts. Also die Effizienz meiner printf-, line- oder 
rectangularfunktionen und deren zusammenspiel im ganzen. Ich hätte halt 
gerne gewusst ob ich um 10er-Potenzen zu langsam bin oder nicht.

So sieht z.B. ein Bildschirminhalt bei mir aus:

von M. M. (blackcow)


Angehängte Dateien:

Lesenswert?

oh displayinhalt vergessen...

von M. M. (blackcow)


Angehängte Dateien:

Lesenswert?

Hmm, des .hex-file is nich so der bringer...

von Ingo (Gast)


Lesenswert?

Du hast nicht wirklich n Hex hochgeladen...

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Auch bei Zugriffen auf Dein Bildschirmspeicherabbild sind Manipulationen 
einzelner Bits ineffizienter als auf Bytegrenzen ausgerichtete Zugriffe. 
Wenn Du beispielsweise einen 8x8-Zeichensatz verwendest, ist das 
Ausgeben eines einzelnen Zeichens mit 8 Schreibzugriffen erledigt, 
sofern die Zielkoordinaten ins Byteraster passen. Wird das Zeichen nur 
um ein Pixel versetzt ausgegeben, musst Du aufwendige Bitmanipulationen 
betreiben - zwei Byte des Bildschirmspeicherabbildes lesen, mit dem 
zurechtgeschobenen Byte aus der Zeichentabelle verknüpfen und wieder in 
das Bildschirmspeicherabbild zurückschreiben.

Klar: Proportionalschrift sieht natürlich schicker aus, aber sie ist 
prinzipbedingt langsamer. Und jede Schriftgröße, die nicht ein 
vielfaches von 8 beträgt (in der Achse, in der die einzelnen Bits eines 
Bytes angeordnet sind), ist entsprechend auch langsam.

von M. M. (blackcow)


Lesenswert?

Also, die Berechnung des Bildinhaltes dauert 10ms. Die Übertragung ans 
LCD nur 15us.

von M. M. (blackcow)


Lesenswert?

Ingo schrieb:
> Du hast nicht wirklich n Hex hochgeladen...

Ja, mit dem Array-Inhalt. Das Format weiß ich jetzt auch nicht sicher, 
aber ich bin selbst drauf gekommen, dass es nicht ganz Zielführend 
ist...

von spess53 (Gast)


Lesenswert?

Hi

>Hmm, des .hex-file is nich so der bringer...

Das Bild aber auch nicht.

MfG Spess

von W.S. (Gast)


Lesenswert?

M. M. schrieb:
> was habt ihr für erfahrung mit rechenzeit von 8-bitter in verbindung mit
> grafik-lcds? das ding ist: ich hab an meinem atmega328 ein lcd mit
> 122x32 pixel drangeklatscht.

Klatsch!

Ja, 8 Bitter und Grafik-Displays sind zumeist Antagonisten.

Bei kleinen monochromen Displays geht es zwar, aber man sollte in jedem 
Fall überlegen, welche Strategie man fährt:

Strategie 1 (grottenschlecht) besteht darin, jedes Pixel und jeden Furz 
direkt über den Controller des Displays zu fahren, also Byte mit Pixel 
auslesen, modifizieren, zurückschreiben. Sowas dauert ewig und ist nur 
was für Leute, die viel zu wenig RAM im System haben. Ist typisch für zu 
kleine 8 Bitter.

Strategie 2 (deutlich besser) besteht darin, im RAM einen Bildspeicher 
zu haben, auf den sämtliche Zeichenoperationen arbeiten. Jede 
Zeichenoperation setzt eine boolean Variable, die von Zeit zu Zeit 
abgefragt wird (so alle 10 ms oder so) und wenn diese gesetzt ist, wird 
der gesamte Bildspeicher en bloc in das Display geschaufelt und die 
Variable zurückgesetzt.

Wie konkret tun? Lernbetty lesen. (tibetanische Gebetsmühle...)

W.S.

von spess53 (Gast)


Lesenswert?

Hi

Strategie 3 Im Rom passende 'Bitmaps' hinterlegen

Beitrag "Re: Zeigt her Eure Kunstwerke !"

Da wird außer auf der Karte kein einzelnes Bit angefaßt.

MfG Spess

von Michael B. (laberkopp)


Lesenswert?

M. M. schrieb:
> für einen screen
> braucht er (20MHz takt) so um die 35ms. d.h. ca. 120 befehle pro pixel,
> bzw. 700000 befehle pro screen.

Ja, ist normal.

Selbst schwarz/weiss Graphik ist unter 8 bit immer etwas sluggish, wenn 
man nicht hochoptimiert in Assembler programmiert (Apple ][/C64 Sprites 
etc.)

von BirgerT (Gast)


Lesenswert?

Hi M. M.,

trotz geputzter Brille - ich finde nicht, welches GLCD Du verwendest 
(Controller Type? und wirklich 122 Pixel breit o. doch 128?); und auch 
nicht, ob Du eine der Bibliotheken zur Ansteuerung des GLCDs verwendest 
oder ob Du Dir das auch selber erarbeitet hast.

Nun ich hatte ein KS0108 kompatibles Display, und war mit dem Zeitbedarf 
zur Ansteuerung (fertige Bibliothek) auch unzufrieden.
Also habe ich auch erst einen GLCD Buffer implementiert..Der Vorteil 
dabei ist, dass der Bufferinhalt auch über den UART an ein Terminal 
ausgegeben werden kann 
http://www.roboter.cc/index.php?option=com_kunena&view=topic&catid=13&id=2411&Itemid=20#3016.

Aber wie jetzt den Buffer an das GLCD ausgeben, ohne für jedes Pixel 
eine Funktion aufzurufen und nur die geänderten Daten zu 
berücksichtigen?!

Also Datenblatt her und selber probiert.. Jetzt brauche ich keinen RAM 
Buffer mehr, jedenfalls nicht mehr für das gesamte Display.

Und 35ms sind normal, wenn man es so macht, wie all die anderen 
(phantasielosen und abgeschriebenen) Bibliotheken:
Adresse schreiben -> Warten -> Daten ausgeben -> Warten -> Adresse 
schreiben.. usw.
Aber so war das wohl nicht im Sinne der GLCD Controller Entwickler.

Wie gibst Du ein ASCII Zeichen aus?

Ich kenne auch nur eine GLCD Lib, die das Zeichnen z.Bsp. im XOR Mode 
unterstützt, alle anderen können nur Pixel auf 1 oder auf 0 setzen.

von m.n. (Gast)


Lesenswert?

Im Prinzip kann man es doch machen, wie man will. Ob man den 
Bildspeicher für XOR zurückliest oder nicht, hängt letztlich von der 
Zugriffzeit darauf ab. Wenn ein read-modify-write im 1-3 µs-Bereich 
liegt, ist das schnell genug.

von M. M. (blackcow)


Lesenswert?

BirgerT schrieb:
> Hi M. M.,
>
> trotz geputzter Brille - ich finde nicht, welches GLCD Du verwendest
> (Controller Type? und wirklich 122 Pixel breit o. doch 128?); und auch
> nicht, ob Du eine der Bibliotheken zur Ansteuerung des GLCDs verwendest
> oder ob Du Dir das auch selber erarbeitet hast.

LCD:
http://www.produktinfo.conrad.com/datenblaetter/175000-199999/187399-da-01-en-Grafik_122x32_LDC_Modul.pdf
Controller:
http://www.lcd-module.de/fileadmin/eng/pdf/zubehoer/ax6120.pdf

> Nun ich hatte ein KS0108 kompatibles Display, und war mit dem Zeitbedarf
> zur Ansteuerung (fertige Bibliothek) auch unzufrieden.
> Also habe ich auch erst einen GLCD Buffer implementiert..Der Vorteil
> dabei ist, dass der Bufferinhalt auch über den UART an ein Terminal
> ausgegeben werden kann
> 
http://www.roboter.cc/index.php?option=com_kunena&view=topic&catid=13&id=2411&Itemid=20#3016.

Also wie oben schon gesagt, ich habe alles selber programmiert. Mit 
internem Buffer im SRAM und komplette Übertragung, nachdem ein Bild 
komplett gezeichnet wurde.

> Wie gibst Du ein ASCII Zeichen aus?

Ich hab im FLASH eine Zeichentabelle für Asci-Zeichen 32-126 für zwei 
Schriftgrößen. Hab ich mit Excel in verbindung mit VBA erstellt :-D
In meinem Programm hab ich eine Funktion printf(), der übergebe ich die 
Anfangskoordinaten, Schriftgröße und den Pointer auf einen String. Diese 
rechnet dann für jedes Zeichen die Koordinaten aus und gibt diese weiter 
an eine Funktion printchar(). Diese Springt dann zur richtigen Position 
der Zeichentabelle und berechnet jede Koordinate des zu zeichnenden 
Pixels des Zeichens extra. Das wird dann an die Funktion setpoint() 
weitergegeben. Diese setzt einfach das betreffende Pixel im 
SRAM-Display-Buffer.
Ausgegeben ans Display wird das ganze erst, nachdem ein komplettes Bild 
fertig ist.

Eine Verbesserung, die weiter oben schon wer genannt hat wäre, in der 
Funktion printchar() nicht einzelne Pixel zu setzen, sondern komplette 
Bytes zu setzen. Halt vorher entsprechend shiften. Das muss ich mir noch 
genauer überlegen obs mir der Aufwand Wert ist.

Was ich auch schon gemacht habe: Ich hatte das gleiche Display und nur 
einen Attiny2313. Dumm wie ich damals war, ist mir beim Bestellen gar 
nicht aufgefallen, das der nicht genug SRAM für einen Buffer hat. Es war 
auf der Platine auch nicht vorgesehen das man den Displayinhalt auslesen 
konnte. Letztendlich hab ich mit gefühlten hundert schmutzigen Tricks 
doch geschafft das ganze ohne Buffer umzusetzen. Das ganze hab ich 
natürlich auch noch in Assembler schreiben müssen :-D Der Flash wurde 
unterm programmieren immer voller. Zum Schluss war ich dann bei 98%. 
Mann hab ich damals geschwitzt. Auf jedenfall ist das Erzeugnis ein 
absolut unwartbarer Spagetticode. Sowas werde ich nie wieder machen!!! 
Ein hoch auf C und genug RAM!!!

von BirgerT (Gast)


Lesenswert?

M. M. schrieb:

> In meinem Programm hab ich eine Funktion printf(),
benutzt Du die printf Funktion aus C (sprintf())? Das ist zwar 
komfortabel aber Speicherhungrig und langsam..

> Ausgegeben ans Display wird das ganze erst, nachdem ein komplettes Bild
> fertig ist.
OK - und wie, immer kompletter Buffer am Stück?
Du hast das im Datenblatt auch mit dem Adressen Auto inkrement gelesen?
Du kannst also die Ausgabeadresse immer an den Pageanfang (0) stellen, 
und dann eine Page komplett mit Daten schreiben, ohne für jedes Byte die 
Adresse neu zu setzen..

> Eine Verbesserung, die weiter oben schon wer genannt hat wäre, in der
> Funktion printchar() nicht einzelne Pixel zu setzen, sondern komplette
> Bytes zu setzen. Halt vorher entsprechend shiften. Das muss ich mir noch
> genauer überlegen obs mir der Aufwand Wert ist.

Ist es - bestimmt..
Jetzt kommt es darauf an, wie der Font und der Buffer aufgebaut sind. 
Idealerweise sind die Zeichenbits horizontal angeordnet, d.h. ein Byte 
entspricht einer Pixelspalte des LCDs.

Je nach dem, wie "hoch" der Font ist, das Font Byte/Word in eine doppelt 
so "hohe" Variable laden, und dann y-Offset mal shiften und Byte für 
Byte auf der richtigen Page ausgeben.

Was auch Speed bringt, erst das Enable-Bit setzen, dann Daten holen und 
auf den Controller schreiben, dann Enable-Bit löschen. Geht bei mir mit 
16MHz und KS0108 kompatiblen Controller, der nur 450ns für das Enablebit 
braucht.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.