Hallo. Ich habe ein DOGM 162 (2x16 Zeichen) und möchte gerne den Cursor beliebig positionieren. Aus dem Datenblatt des verwendeten ST7036 werde ich nicht richtig schlau. Habe mir auch verschiedene Programme angesehen in denen der Cursor z.B. über "set_cursor(pos y, pos x)" gesetzt wird. Das bekomme ich nicht vernünftig bzw. gar nicht hin. Kann mir jemand weiterhelfen?
Harley schrieb: > set_cursor(pos y, pos x) Hast du dir dann auch die entsprechende Funktion angeschaut?
Im Kopf meines Programms steht folgendes: #ifndef x #define x 0x10 //16 #endif #ifndef y #define y 0x2 //Zeile #endif weiter: void set_cursor(unsigned char pos_y, unsigned char pos_x) { SENDEN(y + pos_y * x + pos_x); }
Harley schrieb: > Im Kopf meines Programms steht folgendes: > > #ifndef x > #define x 0x10 //16 > #endif > > #ifndef y > #define y 0x2 //Zeile > #endif > > weiter: > > void set_cursor(unsigned char pos_y, unsigned char pos_x) > { > > SENDEN(y + pos_y * x + pos_x); > > } * und wo ist da jetzt das Commando für "Cursor Positionen" verschlüsselt? Du kannnst ja nicht einfach dem LCD irgednein Byte schicken und das sucht sich dann selber raus, dass du "Cursor positionieren" meinst. * Im Datenblatt steht doch eindeutig, dass die erste Zeile bei 0 und bei einem 2-zeiligen LCD bei 0x40 beginnt. (Cursor Positionieren heißt im Befehlssatz des LCD "Set DDRAM Address"
#ifndef x #define x 0x80 //Zeichen #endif #ifndef y #define y 0x40 //Zeile #endif void set_cursor(unsigned char pos_y, unsigned char pos_x) { SENDEN(y + pos_y * x + pos_x); } set_cursor(0,8); //Cursor soll in Zeile 1 auf Position 8 sein Aber wenn ich das richtig verstehe muss ich für Zeile 1 set_cursor(0x40,00); eingeben und für Zeile 2 set_cursor(0x80,40) eingeben oder?
* was genau macht die Funktion SENDEN gibt die ein Datenbyte (ein Zeichen) ans LCD oder setzt die die Steuerleitungen so, dass das LCD auch weiß, dass es das nächste Byte als Kommando auffasen muss * wo hast du die Formel y + pos_y * x + pos_x her. Die ist ziemlicher Unsinn. Wenn du eine 2-dimensionale Anordnung hast ... +---+---+---+---+---+---+ | | | | | | | +---+---+---+---+---+---+ | | | | | | | +---+---+---+---+---+---+ | | | | | | | +---+---+---+---+---+---+ | | | | | | | +---+---+---+---+---+---+ | | | | | | | +---+---+---+---+---+---+ deren Felder der Reihe nach durchnummeriert sind +---+---+---+---+---+---+ | 0 | 1 | 2 | 3 | 4 | 5 | +---+---+---+---+---+---+ | 6 | 7 | 8 | 9 | 10| 11| +---+---+---+---+---+---+ | 12| 13| 14| 15| 16| 17| +---+---+---+---+---+---+ | 18| 19| 20| 21| 22| 23| +---+---+---+---+---+---+ | 24| 25| 26| 27| 28| 29| +---+---+---+---+---+---+ und wenn wir da einfach mal den Zeilen und Spalten ebenfalls Nummern verpassen 0 1 2 3 4 5 ... Spaltennummer +---+---+---+---+---+---+ 0 | 0 | 1 | 2 | 3 | 4 | 5 | +---+---+---+---+---+---+ 1 | 6 | 7 | 8 | 9 | 10| 11| +---+---+---+---+---+---+ 2 | 12| 13| 14| 15| 16| 17| +---+---+---+---+---+---+ 3 | 18| 19| 20| 21| 22| 23| +---+---+---+---+---+---+ 4 | 24| 25| 26| 27| 28| 29| +---+---+---+---+---+---+ . . Zeilennummer Welche Zahl steht dann im Schnittpunkt der Zeile y und Spalte x? Beispielsweise in der Zeile 3 und Spalte 4 * * * 0 1 2 3 4 5 ... Spaltennummer +---+---+---+---+---+---+ 0 | 0 | 1 | 2 | 3 | 4 | 5 | +---+---+---+---+---+---+ 1 | 6 | 7 | 8 | 9 | 10| 11| +---+---+---+---+---+---+ 2 | 12| 13| 14| 15| 16| 17| +---+---+---+---+---+---+ *** 3 | 18| 19| 20| 21| 22| 23| +---+---+---+---+---+---+ 4 | 24| 25| 26| 27| 28| 29| +---+---+---+---+---+---+ . . Zeilennummer Da steht die 22. So. WEnn du jetzt das Diagramm nicht hast, wie kannst du diese 22 errechnen, wenn du nur die Zeilennummer und die Spaltennummer hast? (hinweis: Zeile 3 bedeutet - weil die erste Zeile ja die Nummer 0 hatte - dass vor dieser Zeile 3 komplette Zeilen waren. Jede einzelne dieser 3 kompletten Zeilen besteht aus 6 Feldern. D.h. die Zeilen 0 bis 2 zusammengenommen sind 18 Felder und in dieser Zeile 3 kommen dann noch 4 dazu, weil ja das Feld in der Spalte 4 gefragt war. 18 + 4 ergibt wieder die 22. Wie lautet also die allgemeine Formel in diesem Fall? Wenn du also diesem gedachten LCD mitteilen willst, dass es den Cursor in Zeile 3, Spalte 4 setzen soll, dann musst du ihm das Commando "Set DDRAM Address" mit einer Adresse von 22 schicken. Und zwar als Kommando(!) und nicht als Datenbyte. Wie lautet die Formel in deinem Fall, wenn eine Zeile nicht 6 Spalten breit ist sondern 0x40 (also 64 Spalten) (auch wenn das LCD von diesen 64 Spalten nur die ersten 16 anzeigt).
> muss ich für Zeile 1 set_cursor(0x40,00); > eingeben und für Zeile 2 set_cursor(0x80,40) eingeben oder? gewöhn dir ganz schnell an, dass wir bei 0 anfangen zu zählen! Und nein, das willst du ja gerade nicht. Du willst die Zeilennummer bzw. die Spaltennummer beim Funktionsaufruf so angeben können, wie es für dich am angenehmsten ist. Die 0x40 interessieren dich nicht, die muss die Funktion selber ins Spiel bringen. Im obigen Beispiel: du rufst auf set_cursor( 3, 4 ) und die Funktion muss sich selber ausrechnen, welche DDRAM Adresse es ans LCD weitergeben muss, damit der Cursor dorthin springt.
void Zeile1() { PORTB&=~(1<<PORTB2); //RS für Kommandoabgabe setzen SENDEN(0x80); // 0x80 = 128 -> Anfang der ersten Zeile _delay_us(40); //Zeit zur Verarbeitung } void Zeile2() { PORTB&=~(1<<PORTB2); //RS für Kommandabgabe SENDEN(0xC0); //0xC0 = 192 -> Anfang der zweiten Zeile _delay_us(40); //Zeit zur Verarbeitung } Habe mein Problem wie oben gelöst. Wollte jeweils nur am Anfang der jeweiligen Zeile anfangen. Vielen Dank für die Hilfe!!!
Harley schrieb: > void Zeile1() > { > PORTB&=~(1<<PORTB2); //RS für Kommandoabgabe setzen > SENDEN(0x80); // 0x80 = 128 -> Anfang der ersten Zeile > _delay_us(40); //Zeit zur Verarbeitung > } > > void Zeile2() > { > PORTB&=~(1<<PORTB2); //RS für Kommandabgabe > SENDEN(0xC0); //0xC0 = 192 -> Anfang der zweiten Zeile > _delay_us(40); //Zeit zur Verarbeitung > } > > Habe mein Problem wie oben gelöst. Gut! Jetzt kann man guten Gewissens sagen: Jetzt hast du es verstanden. > Wollte jeweils nur am Anfang der > jeweiligen Zeile anfangen. :-) Das sagen sie alle. Bis sich dann die Anforderungen ändern. void set_cursor( uint8_t zeile, uint8_t spalte ) { PORTB &= ~(1<<PORTB2); //RS für Kommandabgabe SENDEN( 0x80 + zeile * 0x40 + spalte ); _delay_us(40); //Zeit zur Verarbeitung } oder wenn dir die Multiplikation zu 'lastig' ist (obwohl es wohl keine große Rolle spielen dürfte. Du wartest danach ja sowieso eine gewisse Zeit ab) void set_cursor( uint8_t zeile, uint8_t spalte ) { PORTB &= ~(1<<PORTB2); //RS für Kommandabgabe if( zeile == 1 ) SENDEN( 0xC0 + spalte ); else SENDEN( 0x80 + spalte ); _delay_us(40); //Zeit zur Verarbeitung } Und zur Ausgabe von Kommandos solltest du dir eine eigene Funktion machen. Du brauchst ja zb auch noch Kommandos zum Clear Screen etc. Das ist nicht wirklich schön, wenn du da in jeder einzelnen Funktion erneut am PORTB2 rumpfriemelst. Die kann dann auch gleich den PORTB2 nach der Ausgabe des Kommandos wieder auf Datenmodus zurückstellen.
1 | void SendCommand( uint8_t Command ) |
2 | {
|
3 | PORTB &= ~(1<<PORTB2); //RS für Kommandabgabe |
4 | SENDEN( Command ); |
5 | PORTB |= (1<<PORTB2); //zurückschalten auf Daten |
6 | }
|
7 | |
8 | void set_cursor( uint8_t zeile, uint8_t spalte ) |
9 | {
|
10 | if( zeile == 1 ) |
11 | SendCommand( 0xC0 + spalte ); |
12 | else
|
13 | SendCommand( 0x80 + spalte ); |
14 | _delay_us(40); //Zeit zur Verarbeitung |
15 | }
|
16 | |
17 | void clr_lcd() |
18 | {
|
19 | SendCommand( ... ); |
20 | }
|
21 | |
22 | void cursor_on() |
23 | {
|
24 | SendCommand( .... ); |
25 | }
|
26 | |
27 | ....
|
Wird schon! Weiter so.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.