Hallo Leute,
die hälfte denkt jetzt bestimmt oh man schon wieder ein Topic mit dem
Display ... ja ich weiß, hab auch lange rumgesucht bevor ich schreibe.
Mein Problem besteht zur Abwechslung mal nicht daraus, dass sich das
Display mit meiner Routine nicht initialisieren lässt, sondern darin das
es eben nur manchmal funktioniert (Timingproblem ?)
Also ich will ein DOG-M Display per SPI Schnittstelle ansteuern, die
Schaltung ist wie im Datenblatt bzw. Bild 1. Das Display wird mit 5 V
versorgt. Der /CSB Eingang ist dauerhaft auf Masse gelegt.
Meine Initialisierungsroutine folgt auch dem Datenblatt, siehe Bild 2,
und sieht folgendermaßen aus.
1
voidInitDisplay(void)
2
{
3
inttime;
4
PDR08_P2=0;// Port 08_2 (RS fürs Display) auf Low Schalten
Die Spi Schnittstelle arbeitet sehr langsam - 488 Bit/s, von daher
sollte es ja absolut unkritisch sein. Das MSB wird zuerst gesendet und
die Daten werden so gesendet, das sie auf der positiven Taktflanke
übernommen werden.
Ich hab mir den "Datenstrom" am Oszi angeschaut, sieht alles super aus.
Jetzt ist es so das die ganze Sache halbwegs funktioniert. Soll heißen,
wenn ich das Display 10 mal initialisiere...
Habe ich: 3x Erfolg -> alles ok, Cursor oben links blinkt
2x Mist -> Display initialisiert, aber Cursor blinkt irgendwo
anders
2x wieder Mist -> kein Cursor, aber die "Kästchen" sind zumindest schon
mal leicht grau
3x garkeine Veränderung im Vergleich zum uninitialisiertem Zustand.
Deshalb denke ich das es ein Timingproblem ist... Wie gesagt die Daten
und der Clock kommen sauber am Display an. CSB Leitung liegt auf Low, RS
liegt auch auf low. Ich ahbe schon mit den Zeiten herumgespielt (Die
Variable time bei mir und die 1,3 ms vor dem Entry Mode set). Habe auch
die SPI Schnittstelle mal schneller gemacht. All das hatte überhaupt
keine Auswirkung.
Mir ist jetzt eine Idee gekommen, aber ich glaube ich bin da voll auf
dem Holzweg ? Und zwar, wenn ich den Controller (Jujitzu MB96338)
resette dauert es ja ne Zeit lang, bis das SPI Modul initialisiert ist.
Der SPI CLK Pin hat also kurz ein Low Pegel und dann ein High Pegel
(Ruhezustand des SPI Busses). Kann es sein, das aufgrund diesen
Pegelwechsels das Display jetzt denkt, das zu dem Zeitpunkt ein Bit über
den SPI Bus anliegt ?? Dann Speichert es das Bit als MSB des aktuellen
Bytes ab. Ich schicke jetzt meine 8 Bit echten Daten rüber und nach 7
Bits dieser 8 Bits sagt das Display: ok ich hab ein Byte empfangen,
weiter gehts mit dem nächsten. Und somit ist das LSB meiner Nutzdaten
das MSB des nächsten Bytes, was das Display einließt. Ich hoffe der
Gedanke ist bisschen rübergekommen.
Allerdings kann ich mir nicht vorstellen das dies so eine Problematik
ist, da es sich ja bei jedem Controller so verhält und immer wenn ein
System eingeschaltet wird habe ich ja diesen Effekt.
Ich warte auch Übrigens einen Moment nachdem der Controller (und des
Display) an Versorgungsspannung hängen, befor ich die Daten übertrage.
Wenn ich in der Initialisierungsroutine bin werden immer noch 50ms
gewartet befor's losgeht.
Also ich hab jedenfalls keine Ahnung was es sein kann wie gesagt:
- Signale ok
- Es werden die richtigen Daten übertragen
- Es wird zwischen den Bytes gewartet
- Längere Wartezeiten bringen keine Besserungen
Bin mit meinen Ideen am Ende :(
hmm das würde einiges erklähren. Heißt also die CSB Leitung auf High
Schalten und erst wenn die Kommunikation anfängt auf low Schalten ? Dann
hab ich doch aber das selbe Problem mit dieser Leitung ? Die ist doch
bei Controllerreset auch low und dann setzt der µC sie erst auf High.
Somit empfängt das Display doch auch schon ein Bit was es nicht soll ?
Hab nochmal paar Bilder vom Display drangehängt, also von den
verschiedenen Zuständen.
IMAG0521: Display im nicht initialisierten Zustand bzw. wenn sich garnix
getan hat.
IMAG0522: RICHTIG INITIALISIERT :)
IMAG0523: Cursor an der falschen Position bzw. blinkt oben und unten
IMAG0524 und IMAG0525: falsch initialisiert, aber es hat sich zumindest
was getan
Markus Wi*** schrieb:> Somit empfängt das Display doch auch schon ein Bit was es nicht soll ?
Natürlich muß CSB nach jedem Byte wieder auf high gesetzt werden. Damit
synchronisiert sich das SPI des LCD bei jedem Byte neu.
Ich brauche doch nochmal eure Hilfe.
Hab mir eine Routine geschrieben, die mir ein beliebiges Byte auf das
Display schicken kann und dabei unterscheidet, ob es sich um ein
Steuerbyte oder Datenbyte handelt.
Delay_us(40);// ca 40µs warten, um dem Display Zeit zu lassen
15
PDR08_P0=0;// CSB = Low -> Display empfängt ab jetzt Daten
16
17
if(mode==0)// Steuerdaten senden ?
18
{
19
PDR08_P1=0;// Port 08_1 auf Low Schalten (RS fürs Display)
20
}
21
else// Daten senden
22
{
23
PDR08_P1=1;// Port 08_1 auf High Schalten (RS fürs Display)
24
}
25
26
SPI0SendData(data);// Das Byte ans Display senden
27
Delay_us(40);// ca 40µs warten, um dem Display Zeit zu lassen
28
PDR08_P0=1;// CSB = High -> Display empfängt ab jetzt keine Daten mehr
29
}
Funktioniert auch soweit alles. Jetzt wollte ich eine zweite Routine
schreiben, die auf vorherigen aufbaut und mir ermöglicht Zeichenketten
zu schicken. Ich will also diese Möglichkeit haben:
LcdSendText("Hallo");
Hier die Routine:
while(text[pos]!='\0')// Das Stringende ist noch nicht erreicht ??
16
17
{
18
LcdSendData(text[pos],1);// Das jeweilige byte senden
19
pos++;
20
}
21
}
Irgendwas stimmt jetzt mit der Übergabe der Zeichenkette nicht, wenn die
Funktion über
LcdSendText("Hallo");
aufgerufen wird. Ich komme erst garnicht in die While Schleife rein.
Wenn ich die While schleife durch while(pos<5) ersetze, sehe ich auch
das was mit dem Array Text nicht stimmt, denn dann springt der Cursor
des Displays zwar 5 Spalten weiter nach rechts, aber die vorherigen
Spalten zeigen keinen Inhalt.....
Da ich kein Debugger habe, kann ich leider nicht nachsehen, was sich in
dem Array text befindet.
Andere Leute hier im Forum haben solche Sachen auch mit einem
dynamischen Pointerarray (nennt man es so?) gelöst. Ich dachte auch das
man es so machen kann ??
Vieleicht liegt es am Compiler ? nach dem Motto C ist nich gleich C...
Ich benutze den Softune Workbench Compiler für Fujitzu µC
Danke schon mal
Mir gefallen deine Bitoperationen für die Steuerung der Ausgangspins
nicht.
Warum benutzt du nicht die klassischen Bit Operationen?
Zum Pin setzen:
PORTX |= (1<<PIN_X)
Zum Pin löschen:
PORTX &= ~(1<<PIN_X)
Das was du da tust (Makros?) sieht sehr kryptisch aus bringt nur
schwierigkeiten beim Verstehen des Quellcodes und sorgt für zusätzliche
Fehlerquellen.
Wenn du einen String an einer Routine übergeben möchtest dann reicht es
aus, das du dieser Routine einen Pointer übergibst welcher auf das erste
Zeichen dieser Kette zeigt.
In der Routine welche die Zeichen an das Display schickt, reicht es dann
wenn du den Pointer pro Ausgabe inkrementell erhöhst und überprüfst ob
der Speicherinhalt an diesen Ort ungleich Null ist.
Wenn die Routine dann auf diese Null trifft wurde das
Terminierungszeichen der Zeichenkette gefunden und die Routine wird
wieder verlassen.
So war das We nich da, hab jetzt nochma rumprobiert.
Also das die Ansteuerungen der Ports so aussehen liegt halt am
Controller. Ist halt kein AVR, deshalb auch kein PORTX |= (1<<PIN_X)
usw...
Die Lösung die du Vorgeschlagen hast hatte ich auch schon, allerdings
ohne Erfolg. Meine Lösung macht im Grunde doch nix anderes oder ? Mit
dem Unterschied das deine eleganter ist.
Hier jetzt die "neue" Version (LcdSendData ist gleich geblieben):
while(*text)// Das Stringende ist noch nicht erreicht ??
21
{
22
LcdSendData(*text++,1);// Das jeweilige byte senden
23
}
24
25
}
Ich sollte jetzt also am Display sehen: 1
Was ich sehe: xxxxx, wobei x für irgendein sinnloses Zeichen steht.
Diese Reihe sinnloser Zeichen ist aber bei jedem Aufruf durch
LcdSendText(wort); dieselbe !!
Sieht also so aus als würde er bei irgendeiner anderen Adresse als die
von dem char wort anfangen ?
Bei einem aufruf mit
1
LcdSendText('1');
kommt garkeine Ausgabe.
Bei
1
LcdSendText("1");
Kommen viele sinnlose Zeichen (auch immer dieselbe Zeichenreihe bei
jedem Aufruf). Das Display läuft ein paar mal komplett durch und bleibt
dann stehen (also eine Menge Zeichen).
Wenn ich jetzt nicht nur den Text "1" sondern "Hallo" oder so ausgebe,
habe ich natürlich dieselben Effekte.
Sieht also doch so aus, als würde der Pointer *text meiner Routine
LcdSendText nicht auf den Anfang der Zeichenkette zeigen, sondern
irgendwo anders hin ??
Die Frage ist, ob ich da ohne Debugger überhaupt noch klar kommen kann ?
Gruß Markus
Markus Wi*** schrieb:> Was ich sehe: xxxxx, wobei x für irgendein sinnloses Zeichen steht.> Diese Reihe sinnloser Zeichen ist aber bei jedem Aufruf durch> LcdSendText(wort); dieselbe !!
Welcher Prozessor, welcher COmpiler?
Es gibt Compiler, die auf manchem Prozessoren (PIC und IAR fällt mir da
als erstes ein) aus dem "const" einen impliziten Flash-Zugriff machen,
der µC-intern anders abgehandelt wird, als ein Zugriff aufs SRAM. Da
muss man also peinlich genau unterscheiden, was man eigentlich zur
Verfügung hat.
D.h. dein Problem hat möglicherweise jetzt überhaupt nichts mit dem LCD
an sich zu tun, sondern damit, wie dein Compiler Strings bzw. konstante
Strings in der Schreibweise unterscheidet bzw. behandelt.
> Sieht also so aus als würde er bei irgendeiner anderen Adresse als die> von dem char wort anfangen ?> Bei einem aufruf mit>
1
>LcdSendText('1');
2
>
>> kommt garkeine Ausgabe.
logisch. Das ist schon mal grundfalsch, weil '1' überhaupt kein String
ist und somit schon mal grundsätzlich komplett anders behandelt wird
bzw. behandelt werden muss.
Ja das mit '1' war mit auch klar irgendwie ;)
Also es ist ein Fujitzu MB96F338 Controller.
Als Compiler wird die Softune Workbench V30 verwendet.
Ja ich denke auch das es am Controller liegt. Am Display sicher nicht,
denn dieses funktioniert ja schließlich.
Die Frage ist jetzt wie ich dahinterkomme ?
Markus Wi*** schrieb:> Die Frage ist jetzt wie ich dahinterkomme ?
Tja.
Compilerdoku.
mitgelieferte Beispiele studieren, ob was auffälliges zu sehen ist.
Anderen COde für diesen COmpiler/µC studieren.