Forum: Mikrocontroller und Digitale Elektronik SED1520: Lesen vom Display


von Christian L. (logos23)


Angehängte Dateien:

Lesenswert?

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):
1
unsigned char GLCD_ReadData(void)
2
{
3
unsigned char tmp;
4
5
GLCD_WaitForStatus(0x80, 0);            //Busy-Flag abfragen
6
GLCD_WaitForStatus(0x80, 1); 
7
SED1520_CONTROL_PORT |= SED1520_A0;     //Daten  (nicht Befehl)
8
SED1520_CONTROL_PORT |= SED1520_RW;     //von Display lesen
9
10
SED1520_DATA_DDR = 0x00;           //Daten-Register auf Eingang schalten
11
SED1520_DATA_PORT = 0xFF;          //Interne Pull-Ups einschalten
12
if(lcd_x < 61)
13
    {
14
  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
return tmp;
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

von logos23 (Gast)


Lesenswert?

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.

von Matthias K. (matthiask)


Lesenswert?

Habe vor längerer Zeit mal mit SED1520 gearbeitet (8051er). Read klappte 
damals. Kuck mal nach "READ-MODIFY ON". Unten paar Programmauszüge.
1
// ***********************************************************************
2
// Zeichen eines Punktes positioniert
3
// Übergabe: lcd_x: X-Koordinate 0...121
4
//           lcd_y: Y-Koordinate 0..31
5
//           mode:  0=Pixel löschen 1=Pixel setzen
6
// ***********************************************************************
7
void draw_clear_pixel(byte lcd_x, byte lcd_y, bit mode) {
8
byte code mask_bit_tab[] = {
9
   0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
10
   0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
11
   0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
12
   0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80}; 
13
byte idata mask_bit;
14
bit display_seite;  // 0=linke 1=rechte Displayhälfte je 0...60
15
  if (lcd_x < 61) {
16
    display_seite = 0;
17
    write_lcd_command(lcd_x,0);             // Colum links
18
    write_lcd_command(0xB8 + lcd_y/8,0);    // Zeile/Page 0...3 linke Hälfte    
19
  } else {
20
    display_seite = 1;
21
    write_lcd_command(lcd_x - 61,1);        // Colum rechts
22
    write_lcd_command(0xB8 + lcd_y/8,1);    // Zeile/Page 0...3 linke Hälfte    
23
  }
24
  mask_bit = mask_bit_tab[lcd_y];
25
  write_lcd_command(0xE0,display_seite);    // Read Modify ON
26
  read_lcd_data(display_seite); // Dumy-Read laut Datenblatt SED1520
27
  if (mode) {
28
    // Pixel setzen
29
    write_lcd_data(read_lcd_data(display_seite) | mask_bit,display_seite);
30
  } else {
31
    // Pixel löschen
32
    write_lcd_data(read_lcd_data(display_seite) & ~mask_bit,display_seite);
33
  }
34
  write_lcd_command(0xEE,display_seite);    // Read Modify END
35
}
1
// ***********************************************************************
2
// Lesen eines Zeichens (Daten) vom LCD-Modul
3
// lesen erfolgt aus aktuelle Page/Colum Einstellung
4
// Übergabe: lcd_teil: 0 - linke Displayhälfte
5
//                     1 - rechte Displayhälfte
6
// Rückgabe: Byte: Gelesenes Zeichen
7
// ***********************************************************************
8
byte read_lcd_data(byte lcd_teil) {
9
byte idata lcd_busy = 1;
10
byte idata lcd_byte;
11
12
  // Testen ob LCD-Modul noch im internen Zyklus ist
13
   LCD_RW = 1;
14
   LCD_A0 = 0;
15
   while(lcd_busy) {
16
     if (!lcd_teil) LCD_E1 = 1; else LCD_E2 = 1;
17
     _asm nop; nop; nop; _endasm;     // Impulsverzögerung  
18
     if (!(LCD_DATA & 0x80)) lcd_busy = 0; // BUSY-Flag abfragen
19
     if (!lcd_teil) LCD_E1 = 0; else LCD_E2 = 0;
20
     _asm nop; nop; nop; _endasm;     // Impulsverzögerung      
21
   }
22
   _asm nop; nop; nop; _endasm;     // Impulsverzögerung (nur bei hoher Frequenz)
23
   // LCD-Anzeige ist zum Auslesen neuer Zeichen bereit
24
   LCD_RW = 1;
25
   LCD_A0 = 1;
26
   if (!lcd_teil) LCD_E1 = 1; else LCD_E2 = 1;
27
    _asm nop; nop; nop; _endasm;     // Impulsverzögerung
28
    lcd_byte = LCD_DATA; // Byte vom LCD-Display einlesen
29
   if (!lcd_teil) LCD_E1 = 0; else LCD_E2 = 0;
30
   return lcd_byte;
31
}

von logos23 (Gast)


Lesenswert?

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

von Matthias K. (matthiask)


Lesenswert?

>read_lcd_data(display_seite); // Dumy-Read laut Datenblatt SED1520

...und was ist das?

von logos23 (Gast)


Lesenswert?

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?

von Matthias K. (matthiask)


Lesenswert?

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.

von logos23 (Gast)


Lesenswert?

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
unsigned char GLCD_ReadData() {
3
  unsigned char tmp; 
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
13
    SED1520_CONTROL_PORT |= SED1520_RW;      //vermutlich überflüssig?
14
    SED1520_CONTROL_PORT |= SED1520_A0;
15
    
16
  if(lcd_x < 61)
17
    {
18
  SED1520_CONTROL_PORT |= SED1520_E1;    
19
    asm("nop");asm("nop"); asm("nop");     
20
  tmp = SED1520_DATA_PIN;  
21
  SED1520_CONTROL_PORT &= ~SED1520_E1; 
22
  }
23
  else 
24
    {  
25
  SED1520_CONTROL_PORT |= SED1520_E2;    
26
    asm("nop");asm("nop"); asm("nop");     
27
  tmp = SED1520_DATA_PIN;  
28
  SED1520_CONTROL_PORT &= ~SED1520_E2;  
29
  }
30
 return tmp;
31
}

Im Hauptprogramm:
1
GLCD_WriteString("__"); 
2
GLCD_GoTo(0,0); 
3
4
GLCD_WriteCommand(READ_MODIFY_WRITE, 0);GLCD_WriteCommand(READ_MODIFY_WRITE, 1);
5
  GLCD_ReadData(); test1 = GLCD_ReadData(); 
6
GLCD_WriteCommand(END_READ_MODIFY, 1);GLCD_WriteCommand(END_READ_MODIFY, 1);
7
GLCD_GoTo(0,1); GLCD_WriteHex(test1);

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)

von Matthias K. (matthiask)


Lesenswert?

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?

von logos23 (Gast)


Lesenswert?

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.
1
GLCD_WriteCommand(0x00, 0); //SpaltenCursor
2
GLCD_WriteCommand(0xB8, 0); //ZeilenCursor
3
4
GLCD_WriteCommand(0xE0, 0); GLCD_WriteCommand(0xE0, 1);    //Modify
5
GLCD_ReadData(); test1 = GLCD_ReadData(); 
6
GLCD_WriteCommand(0xEE, 0);  GLCD_WriteCommand(0xEE, 1);  //Modify aus
Er ließt mir dann 0xE0 aus, also die letzte Zahl vor dem Read

1
GLCD_WriteCommand(0x00, 0); //SpaltenCursor
2
GLCD_WriteCommand(0xB8, 0); //ZeilenCursor
3
4
//GLCD_WriteCommand(0xE0, 0); GLCD_WriteCommand(0xE0, 1);    //Modify
5
GLCD_ReadData(); test1 = GLCD_ReadData(); 
6
//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.

von Matthias K. (matthiask)


Lesenswert?

Ohne Deinen vollständigen Quellcode und Schaltplan ist alles nur 
Rätselraten und Zeitverschwendung.

von spess53 (Gast)


Lesenswert?

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

von logos23 (Gast)


Angehängte Dateien:

Lesenswert?

Verzeihung,
im Anhang der Quellcode,
die Anschaltung:
1
/*
2
µC:   ATmega8
3
f_CPU:  1Mhz
4
5
1 A0        -  PC0
6
2 CS2       -  PC1
7
3 CS1       -  PC2
8
4 CL        -  not connected
9
5 /RD(E)    -  5 V
10
6 /WR (R/W) -  PC4
11
7 Vss       -  GND
12
8-15 DB0-7  -  PD0-7
13
16 Vdd      -  5 V
14
17 Res      -  PC5
15
18 VEE      -  -3.0 V
16
17
19,20 EL-Hintergrundbeleuchtung - not connected
18
*/

von logos23 (Gast)


Lesenswert?

spess53 schrieb:
> SED1520_E1/SED1520_E2?
E1 = CS1, E2 = CS2

von spess53 (Gast)


Lesenswert?

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

von logos23 (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

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

von spess53 (Gast)


Lesenswert?

Hi

>Datenblatt z.B Seite 9

Dort steht:

The SED1520 uses a combination of A0, E, R/W, (RD, WR) to identify a 
data bus signal

MfG Spess

von logos23 (Gast)


Lesenswert?

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.
1
 DDRB |= (1<<PB1); PORTB |= (1<<PB1); //E im Init
1
  
2
PORTB &= ~(1<<PB1); //schneller Test  
3
PORTB |= (1<<PB1);

von spess53 (Gast)


Lesenswert?

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

von logos23 (Gast)


Angehängte Dateien:

Lesenswert?

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:
1
unsigned char GLCD_ReadData(void)
2
{
3
unsigned char tmp;
4
5
GLCD_WaitForStatus(0x80, 0); 
6
GLCD_WaitForStatus(0x80, 1);        //Busy-Flag abfragen
7
8
SED1520_CONTROL_PORT |= SED1520_CS1| SED1520_CS2| SED1520_E;  //Vor-Initialisierung  
9
asm("nop");asm("nop"); 
10
11
SED1520_CONTROL_PORT &= ~SED1520_E;  
12
SED1520_CONTROL_PORT |= SED1520_A0;     //Daten  (nicht Befehl)
13
SED1520_CONTROL_PORT |= SED1520_RW;     //von Display lesen
14
 
15
if(lcd_x < 61) SED1520_CONTROL_PORT &= ~SED1520_CS1; 
16
 else SED1520_CONTROL_PORT &= ~SED1520_CS2; 
17
18
asm("nop");asm("nop");
19
20
SED1520_DATA_DDR = 0x00;           //Daten-Register auf Eingang schalten
21
SED1520_DATA_PORT = 0xFF;          //Interne Pull-Ups einschalten
22
asm("nop");asm("nop"); 
23
24
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
return tmp;
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

von spess53 (Gast)


Lesenswert?

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)
1
;                  Daten lesen
2
;                  out      : r17 byte
3
;                  changed : -
4
;
5
rd_dat:            push r16
6
                   rcall rwst_check             ;lcd bereit?
7
                   ldi r16,$00
8
                   out dat_dir,r16              ;porta Input
9
                   cbi ctl_out,enab             ;disab.Anz.
10
                   sbi ctl_out,rw               ;lesen
11
                   sbi ctl_out,cd               ;Daten
12
                   sbi ctl_out,enab             ;Daten gültig
13
                   nop
14
                   nop
15
                   nop
16
                   in r17,dat_in
17
                   cbi ctl_out,enab             ;disp.disab.
18
                   pop r16
19
                   ret

MfG Spess

von Christian L. (logos23)


Lesenswert?

Hey Spess,

danke für den Code-Schnipsel. Ich kann ihn nachvollziehen, und habe ihn 
in C mitbenutzt, leider auch wieder ohne Erfolg.
1
unsigned char GLCD_ReadData(void)
2
{
3
unsigned char tmp;
4
GLCD_WriteCommand(0xE0, 0);          //Modify on
5
GLCD_WaitForStatus(0x80, 0); 
6
GLCD_WaitForStatus(0x80, 1);        //Busy-Flag abfragen
7
SED1520_DATA_DDR = 0x00;           //Input
8
9
SED1520_CONTROL_PORT &= ~SED1520_E;  
10
SED1520_CONTROL_PORT |= SED1520_RW;     //von Display lesen
11
SED1520_CONTROL_PORT |= SED1520_A0;     //Daten  (nicht Befehl)
12
 
13
if(lcd_x < 61) SED1520_CONTROL_PORT &= ~SED1520_CS1; 
14
 else SED1520_CONTROL_PORT &= ~SED1520_CS2; 
15
asm("nop");asm("nop");asm("nop");
16
17
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
return tmp;
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

von spess53 (Gast)


Lesenswert?

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

von Christian L. (logos23)


Lesenswert?

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

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

Anbei alles was ich zu dem Thema habe. Wie gesagt, ohne Gewähr.

MfG Spess

von Matthias K. (matthiask)


Angehängte Dateien:

Lesenswert?

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.

von Matthias K. (matthiask)


Angehängte Dateien:

Lesenswert?

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).

von Christian L. (logos23)


Lesenswert?

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

von Matthias K. (matthiask)


Lesenswert?

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

von Christian L. (logos23)


Lesenswert?

...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

von Matthias K. (matthiask)


Lesenswert?

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.

von Christian L. (logos23)


Lesenswert?

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 ^^.

von Matthias K. (matthiask)


Lesenswert?

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.

von Christian L. (logos23)


Lesenswert?

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

von Matthias K. (matthiask)


Lesenswert?

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.

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
Noch kein Account? Hier anmelden.