Hi,
ich spiele gerade ein wenig mit einem EA DOGM162L-A Display von
Electronic Assembly rum. Funktioniert so weit auch alles super.
Allerdings wollte ich nun noch ein paar selbstdefinierte Zeichen
ausgeben lassen. Das Feld wo das Zeichen ausgegeben werden soll bleibt
aber leer. Hat jemand eine Idee woran das liegen könnte? Programmiert
wird ein M16C28 in C über HEW4. Ansteuerung des Displays erfolgt via
SPI. Vielen Dank für die Hilfe.
Gruß David.
P.S.: Hier mein Code dazu:
Hi
>Das müsste ja die Startadresse des CG RAM sein.
Ist richtig.
> RS=0;> send_command(adress); // CG RAM Adresse setzen> for (i=0;i<8;i++){> send_char(data[i]); // Bitmuster übertragen> }> RS=0;> send_command(0x80);
Setzt 'send_char' RS selbst auf 1? Wenn nicht, fehlt RS=1.
MfG Spess
Hi,
@Ralle: Danke für den Tipp. Das Ergebnis bleibt aber leider das gleiche.
@spess53: Welche Informationen benötigst du denn noch? Hier zumindest
noch die fehlenden Funktionen:
1
voidsend_command(charbyte){//sendet einen Befehl an das LCD
2
CSB=0;
3
for(i=0;i<8;i++){
4
CLK=0;
5
SI=0;
6
if(byte&0x80){
7
SI=1;
8
}
9
byte<<=1;
10
CLK=1;
11
}
12
CSB=1;
13
}
14
15
voidsend_char(charbyte){//sendet ein Zeichen an das LCD
CHAR0_ADR ist wie oben schon beschrieben 0x40, also die Startadresse des
CG RAM. Und arrow_up ist ein Array, welches das Muster beinhaltet und
zeilenweise in den CG RAM geschrieben wird. Line und pos bestimmen
lediglich an welcher Stelle das Symbol ausgegeben wird. Stand hier so in
dem Artikel dass nach einem selbstdefinierten Zeichen eine Position
vorgegeben werden muss.
LCD_GC_CHAR0 entspricht einfach nur einer Null, da die selbstdefinierten
Zeichen ja in die ersten acht Adressen des Data RAM, also 0-7,
geschrieben werden. Oder sehe ich hier irgendetwas falsch?
Ralf G. schrieb:> 'arrow_up': erzeugt für sich persönlich ein Array (wozu sind 'line'> und 'pos'?)
!!
David G. schrieb:> Und arrow_up ist ein Array, welches das Muster beinhaltet
Ja, aber nicht lange!
David G. schrieb:> Selbstverständlich wird das aufgerufen. Mit arrow_up(2,0);
Und was passiert mit der 2 und der 0?
Hi
>Selbstverständlich wird das aufgerufen. Mit> arrow_up(2,0);
Das passt aber nicht zu dem:.
>void generate_char(char adress, const char *data){ // erzeugt eigenes >Zeichen> int i;> RS=0;> send_command(adress); // CG RAM Adresse setzen> for (i=0;i<8;i++){> send_char(data[i]); // Bitmuster übertragen> }> RS=0;> send_command(0x80); // DD_RAM Adresse 0 setzen>}
Du übergibst 'send_command(adress)' eine 2. Da fehlt der Befehl 'Set
CGRAM' (0b01000000) und die Adresse muss ein Vielfaches von 8 sein.
MfG Spess
Ralf G. schrieb:>> Und arrow_up ist ein Array, welches das Muster beinhaltet> Ja, aber nicht lange!
Wieso nicht lange? Kannst du mir das bitte erklären?
Ralf G. schrieb:>> Selbstverständlich wird das aufgerufen. Mit arrow_up(2,0);> Und was passiert mit der 2 und der 0?
Na die 2 steht für die Zeile(1,2) und die 0 für die Position(0...15).
Vielen Dank für deine Geduld mit mir =)
1. Du rufst eine Funktion (arrow_up) mit zwei Parametern auf, die in der
Funktion nicht weiter verwendet werden. (?)
2. Die Variable (arrow_up) in der Funktion (auch arrow_up) wird
initialisiert und das war's auch schon. Zum Funktionsende hat es sich
für die Variable erledigt. Man kann nicht mehr darauf zugreifen (falls
man sie als Wert zurückgibt, dann höchstens zufällig, aber nicht mal das
ist der Fall). Von 'außen' ist die Variable sowieso nicht zu sehen.
3. Falls die Übergabe der Koordinaten irgendwann mal implementiert sein
sollte, ist das doch völlig unsinnig. Wieso ein Zeichen definieren und
dann gleich noch die Position auf dem Display mit dazu?
zu 1.: Die Parameter werden doch verwendet. Sie legen die Position des
Zeichens fest.
zu 2.: Die Variable arrow_up wird initialisiert und dann mittels
'generate_char(CHAR0_ADR, arrow_up);' in den CG RAM auf die Adresse 0x40
geschrieben, also als Zeichen 0 im DD RAM abgelegt.
zu 3.: Die Position habe ich festgelegt, weil hier im Artikel
"Pseudo-Graphische LCD-Ansteuerung" folgender Satz in einem roten Kasten
steht: "Vorsicht: Nach Übertragung eines benutzerdefinierten Zeichens,
muss im LCD-IC explizit eine neue Schreibposition mittels zb
lcd_setcursor, lcd_home oder lcd_clear gesetzt werden."
David G. schrieb:> zu 1.: Die Parameter werden doch verwendet. Sie legen die Position des> Zeichens fest.>> zu 2.: Die Variable arrow_up wird initialisiert und dann mittels> 'generate_char(CHAR0_ADR, arrow_up);' in den CG RAM auf die Adresse 0x40> geschrieben, also als Zeichen 0 im DD RAM abgelegt.>> zu 3.: Die Position habe ich festgelegt, weil hier im Artikel> "Pseudo-Graphische LCD-Ansteuerung" folgender Satz in einem roten Kasten> steht: "Vorsicht: Nach Übertragung eines benutzerdefinierten Zeichens,> muss im LCD-IC explizit eine neue Schreibposition mittels zb> lcd_setcursor, lcd_home oder lcd_clear gesetzt werden."
Trotzdem zeigt dein Code eine Verständnisschwäche auf.
Dem LCD wird EINMAL bekannt gemacht, wie das Zeichen mir dem Code x
auszusehen hat, danach wird dieses Zeichen verwendet. Es besteht daher
überhaupt kein Grund, in der Ausgabefunktion dem LCD jedesmal wieder
klar zu machen, welche Pixel hell und welche Pixel dunkel zu färben
sind.
Daher: die Dinge trennen!
Ist ist eine Sache, dem LCD das Aussehen eines Zeichens zu übermittlen.
Ist es aber eine ganz andere Sache, dieses Zeichen danach zu verwenden.
Und nein, du kannst auf die Art nicht beliebig viele benutzerdefinierte
Zeichen benutzen. Soabld die das Aussehen des Zeichens mit dem Code 2
änderst, werden alle bereits ausgegebenen Zeichen mit genau diesem Code
ebenfalls auf das neue Aussehen geändert.
In der typischen Programmstruktur
int main()
{
Initialisierung
Vorarbeiten
while( 1 ) {
Programmlogik
}
}
fällt die Zeichendefinition in den Bereich Initialisierung, während die
Zeichenausgabe im Bereich Vorarbeiten/Programmlogik vorkommt.
Es kann natürlich vorkommen, dass man während der Programmlogik das
Aussehen eines Zeichens auch einmal ändern muss. Das ist dann aber eher
die Ausnahme, genauso wie es die Ausnahme ist, dass man einen Port
während des laufenden Betriebs in der Ein/Ausgangskonfiguration
umkonfigurieren muss oder einen Timer umkonfigurieren muss. In der
Mehrzahl der Programme werden diese Einstellungen im Bereich
Initialisierung gemacht und bleiben dann während des Programmlaufes
immer gleich, sprich werden nicht mehr verändert.
Hallo Karl Heinz Buchegger,
natürlich hast du Recht. Aber ist das nicht letztlich nur ein
"Schönheitsfehler"? Das dürfte doch an der Funktionalität an sich nichts
ändern, oder?
Aah, mein Fehler!
Karl Heinz Buchegger schrieb:> Trotzdem zeigt dein Code eine Verständnisschwäche auf.
Trotzdem? Da hab' ich mir die Klammern noch mal genau unter die Lupe
genommen.
0b00000100, // #
0b00000000 // hier habe ich eine Klammer 'hingelesen'
}; // hier war für mich die Funktion zu Ende
Ich habe mich an der Stelle festgebissen: Wieso braucht man eine
Funktion um ein Zeichen zu definieren?
David G. schrieb:> Hallo Karl Heinz Buchegger,>> natürlich hast du Recht. Aber ist das nicht letztlich nur ein> "Schönheitsfehler"? Das dürfte doch an der Funktionalität an sich nichts> ändern, oder?
Für das Display wurde ein Zeichensatz erstellt, der fest eingebaut ist.
Nun ist dort im Speicher 'noch etwas Platz' und da kann man sich seine
eigenen Zeichen 'hinmalen'. Sind die einmal dort (bis zum Ausschalten)
ruft man diese, genauso wie alle anderen über ihren ASCII-Code auf (nur
dass man bei z.B. 0x41 bzw. 65 auch 'A' im Quelltext schreiben kann)
Also definiert man die Zeicen nur einmal in einem Array, schreibt sie in
den RAM vom Display und bringt sie später über ihren Index+Offset
(=ASCII-Code) zur Anzeige.
Dann rufe ich zuerst in meiner init-Funktion die arrow_up() auf, und
müsste ja dann später mittels 'send_char(0);' mein Zeichen anzeigen
lassen können. Geht aber nicht...
Hi
Bist du sichcher, das bei Aufruf deiner Funktion auch Instruction Table
0 eingestellt ist? Also irgendwann vorher ein Function Set mit IS[2:1] =
00.
MfG Spess
David G. schrieb:> Dann rufe ich zuerst in meiner init-Funktion die arrow_up() auf, und> müsste ja dann später mittels 'send_char(0);' mein Zeichen anzeigen> lassen können. Geht aber nicht...
Wenn alles richtig initialisiert ist, muss das so gehen.
Allerdings:
Soll das für immer und ewig das einzige Zeichen sein, welches du
definierst?
Willst du da jedesmal eine neue Funktion schreiben?
@spess53: Du hast Recht. Hatte wirklich vergessen auf instruction table
0 zu setzen. Habe das jetzt gemacht. Allerdings immer noch keine Ausgabe
des Pfeils.
@Ralf: Soll selbstverständlich nicht das einzige Zeichen bleiben. Jetzt
muss ich mal ganz dumm fragen: Wie kann man das schöner machen? Also
ohne für jedes Zeichen eine eigene Funktion zu schreiben.
David G. schrieb:> Jetzt> muss ich mal ganz dumm fragen: Wie kann man das schöner machen? Also> ohne für jedes Zeichen eine eigene Funktion zu schreiben.
Gar keine Funktion. Bzw. nur eine kurze. Mal ganz grob:
// Array mit Zeichendaten:
char Zeichen[][] = { ... // hier die 'Zeichnungen' rein
};
for (uint8_t i=0; i < maxZeichen; i++)
ZeichenUebertragen(Zeichen[i][0]);
Ich verzweifel hier noch. Hab mal den gesamten Code angehängt. Kann da
mal bitte jemand drüber schauen und mir sagen warum das nicht
funktioniert? Vielen Dank.
void set_cursor(int line, int pos){
RS=0;
switch(line){
case 1: send_command(0x00 + 0x80 + pos); //Anfangsadresse Zeile 1 +
DB7 high + Position
break;
case 2: send_command(p1=0x40 + 0x80 + pos); //Anfangsadresse Zeile
2 + DB7 high + Position
break;
default:
return;
}
}
was ist den p1=0x40 in Case 2
Oh...Ist mir gar nicht aufgefallen. Hatte das Display vorher über
8-Bitmodus angesteuert und den Quelltext nur auf SPI angepasst. Ist ein
Überbleibsel davon. Geändert, getestet, frustiert. Klappt immer noch
nicht.
for(i=0;i<3;i++){
for (j=0;j<8;j++){
send_char(zeichen[i][j]); //Bitmuster übertragen
}
}
Dein i ist global. Wenn du send_char()
aufrufst ist der letzte Wert von i Geschichte.