Guten Tag,
ich habe mir das Adapter-Board DG-12232 von Pollin gekauft. Das Graphik
LCD wird mittels zwei SED1520-DAA Controller angesteuert.
Hier in dem Forum gab es ja bereits einige Diskussionen darüber (Für
mich hat das keine Hilfe gebracht).
Mein Problem liegt beim Auslesen vom Display.
Wenn ich Daten vom Display lesen möchte, wird immer 0xFF bzw. 0xD8
gelesen. Als Test habe ich eine Spalte mit unterschiedlicher Pixelanzahl
und -anordnung getestet.
Der einzige Beitrag, der das gleiche Problem hatte, gab als Lösung
Zeitpausen ("nops") einfügen an.
Dies habe ich auch versucht, leider ohne Ergebnis.
Im Datenblatt (Anhang) steht der /RD Pin muss auf Low gezogen werden,
allerdings benutze ich das Protokoll der 68er Familie und meines
Erachtens benötigt diese den RD nicht (habe ihn auf VDD angeschlossen,
auf Low würde er den externen Takt aktivieren).
Der Dummy Read wird im Datenblatt als Muss angegeben (wegen Interner
Bus-Leitung?).
Der Quellcode (von hier:
http://www.mikrocontroller.net/attachment/8373/lcd_dip122_1.0.tar.gz):
SED1520_CONTROL_PORT|=SED1520_E1;//Zu Beginn ein "Dummy-Read"
15
asm("nop");asm("nop");//die Daten werden dann vom nächsten
16
SED1520_CONTROL_PORT&=~SED1520_E1;//Aufruf dann sicher abgefragt
17
asm("nop");asm("nop");
18
asm("nop");asm("nop");
19
tmp=SED1520_DATA_PIN;
20
asm("nop");asm("nop");//
21
SED1520_CONTROL_PORT&=~SED1520_E1;
22
}
23
else
24
{
25
SED1520_CONTROL_PORT|=SED1520_E2;
26
asm("nop");asm("nop");
27
SED1520_CONTROL_PORT&=~SED1520_E2;
28
asm("nop");asm("nop");
29
SED1520_CONTROL_PORT|=SED1520_E2;
30
asm("nop");asm("nop");
31
tmp=SED1520_DATA_PIN;
32
SED1520_CONTROL_PORT&=~SED1520_E2;
33
}
34
35
SED1520_DATA_DDR=0xFF;//Datenregister wieder auf Ausgang
36
lcd_x++;//Spaltenvektor inkrementieren
37
if(lcd_x>121)
38
lcd_x=0;
39
returntmp;
40
}
Im Hauptprogramm:
1
GLCD_GoTo(0,0);//dort befindet sich das Pixelmuster
2
test1=GLCD_ReadData();//unsigned char Ausgabe
3
GLCD_GoTo(0,1);//Page 2, Spalte 0
4
GLCD_WriteHex(test1);//Hexadezimale Ausgabe
Ich habe gestern den ganzen Abend damit verbracht, den Denkfehler zu
finden. Auch wenn es für mich keinen Sinn gemacht hat, habe ich für den
RD Pin eine extra Leitung an meinen ATmega8 spendiert und diesen dann
beim Auslesen auf Low gesetzt. Natürlich hat das nichts gebracht.
Kann es sein, dass man nur mit dem 80er Protokoll Daten vom Display
auslesen kann?
Über Hilfe wäre ich euch sehr verbunden.
Wünsche noch einen schönen Tag
B. Christian
Guten Morgen,
Entschuldigt die Aufdringlichkeit, aber ich würde wirklich gerne
verstehen, warum der Read-Befehl nicht funktioniert.
Da ich Daten ans Display schicken kann und der Pin für Read bzw. Write
der selbe ist, kann es eig. kein Hardware Problem sein, sondern muss
einzig an der Sub-Routine ReadData() liegen.
Ich komme einfach nicht mehr weiter. Im Internet finden sich neben den
Datenblatt leider nichts sinnvolles.
Liebe Grüße
Christian B.
Hey, danke für die Mühe und die Antwort.
Also so wie ich deinen Code lese, hast du es ja genauso gemacht wie ich.
Der einzige Unterschied ist der Dummy Read, den du nicht machst (aber im
Datenblatt verlangt wird?).
Kann es möglich sein, dass das Ding in irgendeiner Form einen internen
Defekt hat ? (Kann ich mir nur sehr schwer vorstellen)
Gruß
Christian
Matthias K. schrieb:
>>read_lcd_data(display_seite); // Dumy-Read laut Datenblatt SED1520>>>> ...und was ist das?
Verzeihung, habe mir nur den unteren Teil angeschaut.
Also mir fällt wirklich nichts mehr ein. Weißt du noch was du mit der
/RD Leitung (sofern die bei dir rausgeführt wurde) gemacht hast?
Fällt dir spontan sonst noch etwas ein, was falsch sein könnte. Ich bin
sichtlich verzeifelt.
Achja. READ-MODIFY ON. Inwiefern nutzt du das ? Ich dachte das braucht
man, nur für Curor Blinken.
Lässt du das dauerhaft auf Aktiv?
Habe damals ein DIP122 von http://www.lcd-module.de mit 2x SED1520
Controller benutzt. Ich erinnere mich noch, dass ich die Unterscheidung
der 2 Mode 80/68 damals auch nur schwer verstanden habe.
Habe dann auch das 68-Protokoll verwendet. \RD ist dann der E-Pin und
\WR wird zu R/W. Festgelegt wird das durch den RESET-Pin. H in diesem
Falle für das 68er Protokoll.
READ-MODIFY ON
Legt fest ob nach Read auch die Spalte erhöht werden soll.
Ja habe ich auch so interpretiert und deshalb ist bei mir RD dauerhaft
auf Vdd.
Habe jezt weiter mit nops gearbeitet und deine Version ebenfalls in
abgewandelter Form versucht:
1
2
unsignedcharGLCD_ReadData(){
3
unsignedchartmp;
4
// Testen ob LCD-Modul noch im internen Zyklus ist
5
SED1520_CONTROL_PORT&=~SED1520_A0;
6
SED1520_CONTROL_PORT|=SED1520_RW;
7
8
GLCD_WaitForStatus(0x80,0);
9
GLCD_WaitForStatus(0x80,1);
10
asm("nop");asm("nop");asm("nop");// Impulsverzögerung (nur bei hoher Frequenz)
11
12
// LCD-Anzeige ist zum Auslesen neuer Zeichen bereit
Nun gibt er zwar 0x1F aus, allerding unabhägig davon was an der Stelle
0,0 steht in dem Beispiel hier müsste eig. 0x40 rauskommen (bei 5x7
font).
Entweder ich habe etwas elementares vergessen, oder ich muss mich
langsam damit zufrieden geben, dass ich keine Daten einlesen kann. (was
ziemlich demotivierend wäre)
Das lesen muss auf jedem Fall gehen.
Was meinst Du überhaupt, mit RD dauerhaft auf H? RD ist doch der
betreffende E Pin.
Der Controller ist eigentlich recht schnell, glaube kaum das es an
fehlenden Nops liegt. Eventuell takte den µC mal langsamer.
> tmp = SED1520_DATA_PIN;
Sehe nicht, das Du den auf Input gesetzt hast?
Vielen Dank für deine Mühe,
hatte vorher keine Zeit zu antworten.
- Das DDR habe ich als Eingang geschalten; hatte ich vergessen in den
Quellcode mit reinzuschreiben, das ist es also nicht.
- Ich arbeite sowieso zu Beginn immer mit dem internen 1-MHz-Takt (in
der Hoffnung eine Fehlerquelle weniger zu haben).
- /RD ist bei mir fest auf High-Pegel.
Datenblatt (S.21)=> E(RD) Chip interfaced with 68 family MPU:
Enable Clock signal input for the 68 family MPU.
Er dient nur für den einen Zweck, das LCD am Laufen zu halten.
Etwas interssantes hat sich jetzt herausgestellt, als ich im Main statt
mit Define-Namen die Hexadezimal Sequenzen in den Aufrufen benutzt habe.
//GLCD_WriteCommand(0xEE, 0); GLCD_WriteCommand(0xEE, 1); //Modify aus
Hier ließt er 0xB8, auch wieder die lezte Hexadezimal Zahl.
Dachte schon mein A0 ist in irgendeiner Form invertiert, allerdings wird
bei einem A0 =0 in der Read-Funktion immer 0x40 ausgegeben. Scheint also
schon zu passen.
Stellt sich bei der Schilderung eine mögliche Fehlerquelle heraus?
Anmerk.: Der Übersicht wegen, habe ich hier nur den Cursor der linken
Hälfte, aus der ich auch lesen will reinkopiert.
Hi
>- /RD ist bei mir fest auf High-Pegel.> Datenblatt (S.21)=> E(RD) Chip interfaced with 68 family MPU:> Enable Clock signal input for the 68 family MPU.> Er dient nur für den einen Zweck, das LCD am Laufen zu halten.
Und was ist dann dein SED1520_E1/SED1520_E2?
MfG Spess
Hi
>> SED1520_E1/SED1520_E2?>E1 = CS1, E2 = CS2
Das ist Blödsinn. CS1/CS2 sind die Chipselect Signale um jeweils einen
1520 auszuwählen.
Schreiben: Fallende Flanke von E -> 1520 übernimmt Daten vom Bus
Lesen : Steigende Flanke von E -> 1520 legt Daten auf den Bus
MfG Spess
Datenblatt z.B Seite 9
Für die 68er Family gibt es (wenn ich es richtig interpretiere) nur den
A0 und RW Pin als Steuerleitungen, daneben noch CS1/2 für chip select.
Ich bin dir dankbar, wenn du mich aufklärst
Liebe Grüße
Christian
Hi
>Für die 68er Family gibt es (wenn ich es richtig interpretiere) nur den>A0 und RW Pin als Steuerleitungen, daneben noch CS1/2 für chip select.
Dann sieh dir mal S.36 im Datenblatt an. Dort ist das Timing.
Mit den CS-Leitungen wählst du den 1520 aus, auf den du Schreiben oder
von dem du Lesen willst. Mit E wird der Datenverkehr gesteuert. Bei der
Initialisierung kannst du übrigens beide Chips auswählen und beide
Controller parallel initialisieren.
MfG Spess
Hm, das klingt für mich logisch.
Nur wenn ich den /RD Pin (PB1), was ja im 68er der scheinbare E-Pin ist
an meinen ATmega führe und ihn in der Read-Funktion mit unterbringe.
Wird nichts mehr ab dem Zeitpunkt auf dem Display angezeigt.
Hi
>Hm, das klingt für mich logisch.
Ist es auch.
>Nur wenn ich den /RD Pin (PB1), was ja im 68er der scheinbare E-Pin ist>an meinen ATmega führe und ihn in der Read-Funktion mit unterbringe...
Du wirst da etwas mehr überarbeiten müssen. Deine Write-Funktion ist ja
auch nicht ganz richtig.
MfG Spess
Ok,
ich habe den Code jetzt bearbeitet.
Ich habe bisher eig. nur Librarys nachvollzogen und nicht selbst etwas
alleiniger Hilfe vom Datenblatt geschrieben.
Bezogen auf Seite 36 vom Datenblatt (danke spess53) habe ich versucht
eine Funktion zu erstellen:
SED1520_CONTROL_PORT|=SED1520_E;//Positive Flanke für Befehlsübernahme
25
tmp=SED1520_DATA_PIN;
26
asm("nop");asm("nop");
27
28
SED1520_CONTROL_PORT&=~SED1520_E;
29
SED1520_DATA_DDR=0xFF;//Datenregister wieder auf Ausgang
30
31
asm("nop");asm("nop");
32
SED1520_CONTROL_PORT&=~SED1520_A0&~SED1520_RW;
33
SED1520_CONTROL_PORT|=SED1520_CS1|SED1520_CS2;
34
returntmp;
35
}
Vorab, so funktioniert es auch nicht. Aber passt zumindest die Logik
dahinter? Habe ich die Time Charakteristika richtig gelesen?
Wünsche noch eine gute Nacht und danke für die Geduld
Christian
Hi
Vorab: Ich bin notorischer Assemblerprogrammierer und kann mit deinem
Code nur bedingt etwas anfangen.
>SED1520_CONTROL_PORT |= SED1520_CS1| SED1520_CS2| SED1520_E;
//Vor->Initialisierung
>asm("nop");asm("nop");
Du solltest deine Routinen etwas hierarchischer aufbauen. Um ein Byte zu
lesen (oder zu schreiben) ist es egal, welcher SED1520 ausgewählt ist.
D.h. in der untersten Ebene hat die CS1/2-Ansteuerung nichts zu suchen.
CS1 oder CS2 werden anhand der Spaltenadresse (Column) gesetzt und
danach die Read/Write-Routine aufgerufen.
Die 'nop's' kannst du dir auch sparen.
Falls es dir hilft, meine 'Read'-Routine für den SD1520 (Stand
25.3.1999)
SED1520_CONTROL_PORT|=SED1520_E;//Positive Flanke für Befehlsübernahme
18
tmp=SED1520_DATA_PIN;
19
SED1520_CONTROL_PORT&=~SED1520_E;
20
SED1520_CONTROL_PORT|=SED1520_E;
21
SED1520_DATA_DDR=0xFF;//Datenregister wieder auf Ausgang
22
GLCD_WriteCommand(0xEE,0);//Modify out
23
returntmp;
24
}
Ich verstehe, das nach dem Datenblatt zum Schluss Enable wieder auf Low
gesetzt werden sollte, allerdings führt dass bei mir zu einem nicht
weiter beschreibbaren Display ab dem Zeitpunkt, wo Enable nicht wieder
auf High gesetzt wird.
Ich habe jetzt über eine Woche versucht den Code anzupassen und bin
dementsprechend ziemlich angepisst.
Wäre es möglich, dass du mir deine asm-lib schicken könntest und ich die
einmal testen könnte?
Anm: Das mit der Hierarchie und so weiter leuchtet mir ein, ich wollte
aber erst mal auf Funktionalität testen.
Mfg
Logos
Hi
>allerdings führt dass bei mir zu einem nicht>weiter beschreibbaren Display ab dem Zeitpunkt, wo Enable nicht wieder>auf High gesetzt wird.
Das kann möglicherweise auch an dem fehlenden Schreibzyklus liegen. Lass
doch einfach mal alles Unwichtige, wie CS-Umschaltung und
Read-Modify-Write,
weg. Also einfach Adresse auf Null setzen. Byte schreiben. Adresse
wieder
auf Null. Dummybyte lesen. Byte lesen. Wenn das klappt kannst du dich um
den Rest kümmern.
>Wäre es möglich, dass du mir deine asm-lib schicken könntest und ich die>einmal testen könnte?
Wie gesagt. Ich habe die Datei vor fast 11 Jahren das letzte mal
angefasst.
Und ich kann beim besten Willen, jetzt auch nicht genau sagen, ob alles
bis zum Letzten getestet ist. Ansonsten kein Problem.
MfG Spess
Guten Abend Spess,
ich versuche jetzt von Null anzufangen, was bedeutet für dieses "banale"
Problem noch mehr Zeit zu investieren. Ich hasse es, das ich das
unbedingt verstehen will, aber es ist nun mal so.
Wenn es für dich keine Umstände macht, wäre ich dankbar für die Dateien.
Wenn dies dann wirklich funktioniert, ist die Fehlersuche einfacher bzw.
schneller und ich kann mit den. eig. Dingen anfangen.
Als dann nur noch mal Danke zu sagen bleibt.
Schöne Grüße
Logos
Christian L. schrieb:
> ich versuche jetzt von Null anzufangen
Ich hänge mal meinen SED1520-Code an. Ist für DIP122 von EA. Hat aber
einen PIN weniger rausgeführt. Gerade nochmal ausprobiert. Läuft hier
selbst mit 18MHz Quarz ohne weitere Delays auf Atmega644. Auch
read-Funktion ist ok.
Das Bild sollte Klärung bringen für den 68 Mode bei Deinem Display. Du
muss die CS-Signale noch jeweils in die write und read-Funktionen
einbinden, je nachdem welche Hälfte aktiviert wird. Alles andere kann
bleiben A0 R/W und E ist wohl intern parallel geschaltet.
Und nicht vergessen, RES auf H zu setzen, oder besser eine L/H Flanke
erzeugen und den RES-Pin dann dauerhaft auf H lassen (aktiviert den 68er
Mode).
Tag,
also das letzte Aufgebot. Danke für eure Quellcodes, leider haben, die
mich auch nicht weiter gebracht. Heute ist der letzte Tag, den ich an
das Display verschwenden werde.
Eine Verständnisfrage hätte ich noch. Wenn man sich das Datenblatt
anschaut und das Timing Diagramm für den "68" Modus, würde ich mein
Read() verbal so ablaufen lassen:
- DDR_Daten auf Eingang schalten
- E_low setzen
- RW_high setzen
- CS1 oder CS2_low setzen
- evtl. hier einen nop einfügen
- E_high setzen
- evtl. hier einen nop einfügen
- daten = Daten_PIN
- evtl. hier einen nop einfügen
- Alle vorherigen Einstellungen rücksetzen (RW_low, CS1/2 _high, E_high)
- DDR Daten auf Ausgang rückstellen
Wenn mir nur jemand noch sagen könnte, ob das wenigstens so passt, wäre
ich schon froh.
Schöne Grüße
Logos
Christian L. schrieb:
> - DDR_Daten auf Eingang schalten> - E_low setzen> - RW_high setzen> - CS1 oder CS2_low setzen> - evtl. hier einen nop einfügen> - E_high setzen> - evtl. hier einen nop einfügen> - daten = Daten_PIN> - evtl. hier einen nop einfügen> - Alle vorherigen Einstellungen rücksetzen (RW_low, CS1/2 _high, E_high)> - DDR Daten auf Ausgang rückstellen
Du hast einiges der Signalreihenfolge und der Aktivitätspolaritäten
durcheinander gebracht, versuchs mal so:
Ausgangszustand:
- RES ganz am Anfang auf High und immer so lassen (68er Mode)
- RW beliebig
- A0 beliebig
- CS1 high
- CS2 high
- E low
READ:
Zum testen gar nicht warten auf Busy, sondern erstmal ein
_delay_ms(10); verwenden, dann:
- DDR_Daten auf Eingang schalten
- Pullups zuschalten
- RW_high setzen
- A0_high setzen
- CS1 oder CS2_low setzen
- _delay_us(1);
- E_high setzen
- _delay_us(1);
- daten = Daten_PIN
- _delay_us(1);
- E_low setzen
- CS1/2_high setzen
- Pullups abschalten
- DDR Daten auf Ausgang rückstellen
...und ich wollte wirklich aufgeben.
Matthias K. schrieb:
> Ausgangszustand:> - RES ganz am Anfang auf High und immer so lassen (68er Mode)> - RW beliebig> - A0 beliebig> - CS1 high> - CS2 high> - E low
Wenn es nicht so ewig lang gedauert hätte, würde ich lachen. So bin ich
einfach nur dankbar, dass ich endlich aufhören kann, darüber
nachzudenken.
Mein Fehler war, dass ich den Rest der Funktionen, die vermeintlich
funktionierenden Methoden so belassen habe, wie sie in der von mir
übernommenen Bibliothek vorhanden waren.
Ich habe deine Reihenfolge mit dem Zeitdiagramm peinlich befolgt und
zwar jetzt bei allen !!!
Ergebnis ist jetzt, das alles funktioniert.
Jetzt gehts an die Optik und die Zeitoptimierung.
Ich danke euch beiden vielmals für die Geduld und die Hilfe.
Ich hoffe jetzt habe ich das geschnallt.
Ich wünsche noch einen schönen Sonntag
Christian
freut uns...
Hoffentlich setzt Du das Programm dann in die Codesammlung, zu der
SED1520 Display-Variante mit den 2 rausgeführetn CS-Anschlüssen gibt
hier gelegentlich Unklarheiten.
Natürlich,
Die Bibliothek, die ich hier aus dem Forum habe, ist dementsprechen
inkorrekt:
Beitrag "SED1520 Lib von avr-lcd.de?"
Solange man nicht vom Display Daten lesen möchte funktioniert sie,
solange man den beim Code nicht berücksichtigten E(/RD)-Pin auf High
Pegel zieht.
Ich kenne nicht wirklich die Regeln und Normen von solchen Programmen.
Von daher sei dann eher auf Inhalt Wert gelegt als auf das Äußere ^^.
Man kann auch ganz ohne READ klarkommen, wenn zB. im RAM eine Art
Bildspeicher vorhält und alle Änderungen erstmal dort macht und dann zum
Display überträgt, wie beim PC praktisch. Belegt natürlich 122x4 Byte
SRAM. Busy-Zustand müsste man dann über großzügige Delays regeln. Die
READ-Variante ziehe ich aber auch vor.
Naja der ATmega8 ist ja nicht unbedingt ein Speicherwunder. Mir ging es
aber auch eher ums Prinzip und Verständnis.
Habe das Ganze jetzt in die Codesammlung gestellt
Beitrag "DG-12232 Ansteuerung von 2xSED1520 Controller"
Ich habe auch für mich eine Zusammenfassung geschrieben, die ich dann
doch online stellen wollte. Für diejenigen, die auch länger für sowas
brauchen. Dabei habe ich deine Anmerkung
Matthias K. schrieb:
> READ:> Zum testen gar nicht warten auf Busy, sondern erstmal ein> _delay_ms(10); verwenden, dann:>> - DDR_Daten auf Eingang schalten> - Pullups zuschalten> - RW_high setzen> - A0_high setzen> - CS1 oder CS2_low setzen> - _delay_us(1);> - E_high setzen> - _delay_us(1);> - daten = Daten_PIN> - _delay_us(1);> - E_low setzen> - CS1/2_high setzen> - Pullups abschalten> - DDR Daten auf Ausgang rückstellen
mit reingenommen. Wenn du das als störend oder unpassend empfindest,
sage mir bitte Bescheid.
Schönen Abend noch
Gut gemacht, die .doc ist sicher auch hilfreich. Der Code sieht ganicht
so schlecht aus, von der Form her. Da wurden hier schon deutlich
schlechtere Dinge abgeliefert.