C Zeichnen mit einem GLCD

Dieses Thema im Forum "Software" wurde erstellt von Janiiix3, 19. Januar 2018.

  1. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Endlich mal wieder Freitag und ein bisschen Zeit zum basteln :p

    Aktuell möchte Ich mich mal tiefer mit den GLCD´s beschäftigen.
    Meine Frage dazu lautet...

    Wie zeichne Ich am besten? Arbeite Ich auf dem quell µC mit einem VRAM oder zeichne Ich direkt in den RAM vom GLCD µC?

    Als erstes möchte ich ein ganz einfaches Rechteck zeichnen..

    Der Nachteil von einem VRAM für den quell µC ist der Speicherbedarf... Wenn ich jetzt ein 64 x 128 GLCD habe, brauche ich ja schon ->



    CodeBox C und C++
    char VRAM[64][128];
    
     
  2. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Grundsätzlich gehe ich davon aus, daß Du kein "intelligentes" Display mit eingebauten Zeichenroutinen meinst.
    Das kommt darauf an...;)

    ... zB, ob Du Daten vom Display überhaupt zurücklesen kannst. Üblicherweise adressierst Du ja erstmal eine Page (Zeile mit acht untereinanderliegenden Pixeln) und eine Spalte, und schreibst mit einem Datenbyte die acht Pixel. Um nur einen dieser Pixel zu setzen (oder zu löschen), müßtest Du also erstmal den Ist-Zustand dieser acht Pixel auslesen (->read), dann den konkreten Pixel setzen (oder löschen -> modify), und anschließend das ganze zum Display senden (->write). RMW.
    Du hast also mehr Traffic auf dem Display-Bus, den Du Dir bei Verwendung von seperatem Speicher sparen kannst.
    Es gibt (wie angedeutet) Displays, bei denen gar nicht zurückgelesen werden kann (zB weil MISO bei SPI nicht verdrahtet/kontaktiert ist...).
     
  3. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Willst du also darauf anspielen, dass ich lieber einen VRAM nehmen sollte?
     
  4. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Nein, das kommt darauf an...

    Wenn Du keine Daten zurücklesen kannst, mußt Du den Ist-Zustand anders herleiten. Entweder mittels Abbild (VRAM), oder "irgendwie anders".
    Wenn Du keine Daten zurücklesen willst (weil Dir das z.B. zu lange dauert...), willst Du den Ist-Zustand anders ermitteln.

    Bei meinen kleinen OLEDs zB könnte ich zwar den Speicher auslesen, aber bei 16x96 Pixeln macht das nicht viel Sinn. Da kommt erstmal nur ein 12pt-Text drauf, und drunter 3 Pixel für'n Balken.
    Bei Textänderungen muß eh immer alles geschrieben werden, da kann ich den Wert des Balkens auch jedesmal mitverORren.
     
  5. Dirk

    Dirk Administrator
    Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.198
    Zustimmungen:
    119
    Punkte für Erfolge:
    63
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Zu dem Thema, schau dir einmal dieses Projekt an. Vielleicht bringt dich das auf Ideen :)
     
  6. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    264
    Zustimmungen:
    19
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Wenn es sich um ein einfarbiges Display handelt:


    CodeBox C und C++
    char VRAM[8][128];

    Auch das lohnt sich nur für einen µC, der deutlich mehr als 1 kB RAM hat.
     
  7. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Stimmt natürlich, 8 Byte für 64 Pixel pro Spalte...
    Man könnte ja auch einen Teil des Displays im SRAM virtualisieren, und einen Teil fest beschreiben. Kommt halt auf die konkrete Anwendung an.
    Wenn der Controller-Speicher nicht reicht, kann auch externer Speicher 'ne Option sein...
     
  8. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    264
    Zustimmungen:
    19
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Genau.
    Und wenn es nicht zeitkritisch ist, kann man auch das ganze Bild neu schreiben, dann braucht man gar kein VRAM.
     
  9. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Mit dem Array


    CodeBox C und C++
    char VRAM[64][128]
    

    Wollte Ich eigentlich ein komplettes Abbild vom GLCD erstellen.

    Texte kann Ich schon darstellen.

    Was noch nicht so klappt ist eben zeichnen. Erstmal wollte Ich ein einfaches Rechteck zeichnen.
    Das haut noch nicht ganz so sauber hin wie Ich es mir vorstelle.

    Mit diesen beiden Funktionen habe Ich versucht ein Rechteck zu zeichen.
    Sind diese Funktionen überhaupt korrekt? Ganz speziell was Ich mir da zusammengebaut habe, mit den Parametern laut Datenblatt?



    CodeBox C und C++
    void glcd_column(uint8_t column)
    {
       uint8_t LowByte       = 0;
       uint8_t HighByte   = 0; 
     
       /* Build High Byte */
       HighByte |= 0x10;
       if (column & 1<<7)
           HighByte |= 1<<3;
       if (column & 1<<6)
           HighByte |= 1<<2;
       if (column & 1<<5)
           HighByte |= 1<<1;
       if (column & 1<<4)
           HighByte |= 1<<0;
     
       /* Build Low Byte */
       if (column & 1<<3)
           LowByte |= 1<<3;
       if (column & 1<<2)
           LowByte |= 1<<2;
       if (column & 1<<1)
           LowByte |= 1<<1;
       if (column & 1<<0)
           LowByte |= 1<<0;
     
       glcd_sendcmd(HighByte);
       glcd_sendcmd(LowByte);
    }
    
    void glcd_row(uint8_t row)
    {
       glcd_sendcmd(0x40 | (row));
    }
    


    https://www.lcd-module.de/eng/pdf/zubehoer/st7565r.pdf
    ab Seite 41 geht es los.

    Mit diesen Funktionen die Ich mir geschrieben habe, müsste Ich doch an die Position "x,y" vom Display kommen und schreiben können oder?
     
  10. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Die Displays besitzen ja ihren eigenen Speicher, den man zum setzen oder löschen einzelner Pixel auslesen muß (da immer ein ganzes Byte geschrieben wird).
    Wenn man den nicht auslesen kann oder will, muß man die Bilddaten woanders Speichern, ein Abbild des Speichers im Controller (oder zusätzlicher externer Speicher) zB.
    Wenn einfach jedesmal das ganze Display neu gezeichnet werden soll, mußt Du Dir aber auch irgendwo die zu zeichnenden Inhalte merken.
    Wenn man (wie in meinem Fall) das Bild aus einigen Werten berechnen/von Speicheradressen laden kann, wird das recht einfach - aber wenn der Benutzer zB zur Laufzeit irgendwas draufzeichnen soll, wirds komplexer.

    Kommt drauf an, wie das Display genutzt werden soll, was letztendlich darauf dargestellt werden soll...

    Das Datenblatt bekomm ich am Tablet grad nicht geladen... aber warum diese komplizierte If-Abfragerei? -> Bits schubsen...

    Was soll da eigentlich geschehen?
    Es ist ein Byte Column gegeben.
    Es soll ein Byte Highbyte berechnet werden - genauer: Highbyte soll das obere Nibble von Column rechtsorientiert enthalten, zusätzlich soll Bit 5 gesetzt sein, also Highbyte= Column>>4 OR 0x10 (oder column>>4 + 1<<4)
    Das Lowbyte soll einfach nur das untere Nibble von Column sein? Lowbyte=Column AND 0x0F ?

    Noch'n Nachtrag: unter ASM würde man statt viermal rechtsschieben einfach die Nibbles SWAPpen (eine Instruktion), und anschließend das obere Nibble wegmaskieren (ANDI mit 0x0F, eine Instruktion). Das OR bzw die Addition für die "1" im oberen Nibble bleibt zusätzlich, klar.
    Inwiefern C SWAP unterstützt, muß ein C-Profi sagen...
     
    #10 LotadaC, 20. Januar 2018
    Zuletzt bearbeitet: 20. Januar 2018
  11. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Du hast total Recht, das war viel zu aufwendig^^


    CodeBox C und C++
    void glcdSetColumn(uint8_t column)
    {
       uint8_t lowByte       = 0;
       uint8_t highByte   = 0;  
      
       /* Build High Byte */
       highByte = ((column>>4) | 0x10);
      
       /* Build Low Byte */
       lowByte = (column & 0x0F);
      
       glcd_sendcmd(highByte);
       glcd_sendcmd(lowByte);
    }
    
     
    #11 Janiiix3, 20. Januar 2018
    Zuletzt bearbeitet: 20. Januar 2018
  12. Dirk

    Dirk Administrator
    Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.198
    Zustimmungen:
    119
    Punkte für Erfolge:
    63
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Sorry, wenn ich hier einfach so "rein platze", wo ich jetzt was vom ST7565 lese ...

    Ich hatte ja schon einmal auf ein Projekt bei den Ressourcen hingewiesen.

    Da verwende ich ein Display mit ST7565R-G Controller
    Es wäre eventuell sinnvoll das man anzuschauen.


    Das Projekt nutzt einen Atmega32

    Im SRAM habe ich den Grafikspeicher des Displays abgebildet (unabhängig von der Organisation des Grafikspeichers im Display, also Pages zum Beispiel, unabhängig vom Display, 1 Bit pro Pixel).

    Es gibt eine Funktion DrawPixel, die kann an der Position (X;Y) des Grafikspeichers im SRAM ein Pixel sezten/löschen.

    Diese Funktion wird von weiteren Grafikfunktionen genutzt. Linie, Rechteck, Kreis, Font, Bildschirm löschen/füllen, Zahlen ...

    Landscape und Portrait Modus wird unterstützt, auch diverse Funktionen wir OR XOR AND beim Schreiben in den Grafikspeicher.

    Das ganze ist also erst mal unabhängig vom verwendeten "einfarbigem" Display und eigentlich auch unabgängig vom verwendeten Mikrocontroller oder der Mikrocontrollerfamilie.

    Nun gibt zwei Bereich die angepasst werden müssen:
    (1) SPI Schnittstelle
    Im Projekt habe ich wahlweise SoftwareSPI und HardwareSPI AVR/Xmega verwendet. Das muss an den Mikrocontroller angepasst werden.

    (2) Display Protokoll
    Funktion Display_Update, diese Funktion kopiert den Grafikspeicher vom SRAM in den Grafikspeicher des Displays. Das muss an das Display angepasst werden.
    Das Display hat den Controller ST7565R-G, also anpassen muss man nicht viel,
    ausser vielleicht die Initialisierung des Displays, Kontrast...
     
  13. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Danke @Dirk .
    Ich will es lernen und versuchen das mal selbst auf die Beine zu stellen.
     
  14. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    upload_2018-1-20_12-2-59.png

    Für mich hat das Display Physikalisch gesehen "63x127" Bildpunkte.
    Wenn ich jetzt ganz unten ans Display schreiben möchte, reicht dann nicht einfach Column auf sagen wir mal "0" und "Start Line" auf "63" zu setzen? Oder muss ich auch was mit den Pages machen?
     
  15. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Ist es vill. so besser zu verstehen und effektiver?


    CodeBox C und C++
    void glcdSetAddress(uint8_t column, uint8_t row)
    {
       /*
       *   Baue das Kommando für die Zeile
       */
       glcdSendCmd((column>>4)|1<<4);
       
       /*
       *   Adresse
       */
       glcdSendCmd(column & 0x0F);
       
       /*
       *   Setze die Reihe
       */
       glcdSendCmd((row)|1<<6);
    }
    
     
  16. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    264
    Zustimmungen:
    19
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Vermutlich sind es 64 Zeilen (von 0 bis 63 durchnummeriert) und 128 Spalten (von 0 bis 127),
    wobei die 64 Zeilen in 8 Seiten unterteilt sind.
    Start Line benutzt man üblicherweise zum scrollen.
    Aber sicher. Als erstes solltest Du den Speicheraufbau auf Seite 27 verstanden haben.
    Um einen Punkt zu setzen braucht man die Befehle Page Address Set, Column Address Set und Display Data Write.

    Wenn Du das wirklich alles selbst neu schreiben willst, wirst Du wohl nicht umhinkommen, Dich mal ein paar Tage mit dem Datenblatt zu beschäftigen und wenn Du den Bresenham-Algorithmus noch nicht programmiert hast, werden wohl noch mal ein paar Tage dazukommen. ;)
     
    #16 Mikro23, 20. Januar 2018
    Zuletzt bearbeitet: 20. Januar 2018
  17. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Ob ich nun die "Page" Adressiere oder die "Page Line" ist doch relativ oder?

    upload_2018-1-20_21-7-15.png
     
  18. Mikro23

    Mikro23 Mitglied

    Registriert seit:
    2. Januar 2017
    Beiträge:
    264
    Zustimmungen:
    19
    Punkte für Erfolge:
    18
    Sprachen:
    C, Assembler
    Was meinst Du mit Page Line? Den Befehl gibt es nicht im Datenblatt.
    Du kannst Page und Column nur setzten.
    Display Start Line Set verschiebt nur die Startadresse des internen RAM.
    Keiner der Set-Befehle schreibt überhaupt irgendwelche Daten ins RAM.
     
  19. Janiiix3

    Janiiix3 Aktives Mitglied

    Registriert seit:
    28. September 2013
    Beiträge:
    1.278
    Zustimmungen:
    8
    Punkte für Erfolge:
    38
    Sprachen:
    C
    Folgendes..
    Jede Page hat ja "8 Lines" (D0-D7).. Mit "Display Start Line Set" kann Ich doch auswählen wo auf der "x" Achse Ich anfangen will zu schreiben? Das dass keine Schreibbefehle sind ist mir schon klar.
    Wenn ich jetzt den Befehl für die "Display Start Line Set" dem Display sende z.B glcdSendCmd(1<<6 | LINE_ADDRESS); Müsste ich doch an "LINE_ADDRESS" sein und könnte da anfangen in den RAM zu schreiben?
     
  20. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.979
    Zustimmungen:
    45
    Punkte für Erfolge:
    48
    Sprachen:
    BascomAVR, Assembler
    Daß mit Data Write zu schreiben ist, wird Jan klar gewesen sein. Ihm gings eher um das Ziel wohin geschrieben werden soll.

    Ich vermute(!), Jans Gedankengang war folgender: Wenn die Page (default) auf Page0 gesetzt ist, kann man Page1 (Zeile2 im physischen Display) vielleicht beschreiben, indem man die Daten nach Page0 schreibt, und die Startline verschiebt. Damit könnte der Inhalt korrekt in der zweiten Zeile (des Displays) landen - aber eben auch das ganze Display verschoben sein. Insbesondere würde der Inhalt von Page8 in der ersten Displayzeile erscheinen.

    Bei einem Display mit max 32 Zeilen kann man dann auch zwei "Bilder" in den Speicher schreiben, und mit der Startline zwischen beiden wechseln?
     
  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)
  1. Diese Seite verwendet Cookies, um Inhalte zu personalisieren und die Seite optimal für dich anzupassen. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden