Forum: Mikrocontroller und Digitale Elektronik OLED-Display SPI Psoc4


von Flor B. (florben)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich versuche ein OLED-Display über die SPI-Schnittstelle meines PsoC 4 
Entwicklerboards zu betreiben. Leider bisher ohne erfolg.

Das Display ist ein Raystar 128x128 OLED-Display mit SSD1327ZB 
Controller (Datenblatt Siehe Anhang).
Ich habe das Display nach vorgaben des Datenblatts angeschlossen und ein 
kleine Initialisierung dazu geschrieben.
Pin:
1-->Ground
2-->5V
3-->Ground
4-->3V
5-->Ground
6-->Ground (SPI Mode)
7-->Ground (SPI Mode)
8-->nicht angeschlossen
9-->200k Ohm auf Ground
10-->Ausgang P0.0 Psoc4
11-->Ausgang P0.2 Psoc4
12-->Ausgang P0.1 PSOC4
13--> nicht angeschlossen
14--> nicht angeschlossen
15--> SCLK
16--> SDIN
17--> nicht angeschlossen
18--> nicht angeschlossen
19--> nicht angeschlossen
20--> nicht angeschlossen
21--> nicht angeschlossen
22--> nicht angeschlossen
23--> nicht angeschlossen
24--> nicht angeschlossen


Zur SPI-Schnittstelle habe ich noch drei weitere benötigten digitale 
Ausgänge hinzugefügt.

CS-> Chip Select
DC-> Data/Command Control
RES-> Reset Signal

Das Display macht leider überhaupt nichts. Ich nehme an mein Programm 
ist fehlerhaft.

Über Hilfe würde ich mich freuen

Danke im Voraus.

von pegel (Gast)


Lesenswert?

Ich habe kein SSD1327 OLED hier.

Wenn ich in eine Situation komme wo gar nichts geht, schaue ich wie 
andere das gemacht haben.

https://github.com/ClockSelect/myevic/blob/master/src/SSD1327.c

Schon die Initialisierung ist sehr verschieden und von Timing, wie bei 
PowerOn, sehe ich bei dir auch nichts.

von Flor B. (florben)


Angehängte Dateien:

Lesenswert?

Ich habe nun ein hilfreiches Muster gefunden und mein Hardwareaufbau 
etwas optimiert.

Was mir noch Probleme bereitet ist die Funktion der Bildausgabe.
Wenn ich den Bild-Code "pic1" an die Ausgabefunktion "Pic_show()" 
übergeben will nimmt er die Daten nicht an.

So war es auch im Beispiel-Programm gelöst.



 int main(void)
{
    SPIM_Start();


       Power_On();
       Write_Cmd(0xAE);  //Set Display OFF
      Initial_SSD1327();
    Pic_show(&pic1);// Ausgabe an Display

      Write_Cmd(0xAF);  //Set Display On


}

void Pic_show(unsigned char ptr[][MAX_COL/2]){
  unsigned char i=0,j=0;

  Write_Cmd(0x15);  //Set Column Address
  Write_Cmd(0x00);  //Start Column Address
  Write_Cmd(0x3F);  //End Column Address

  Write_Cmd(0x75);  //Set Row Address (segment)
  Write_Cmd(0x00);  //Satrt Row Address
  Write_Cmd(0x7F);  //End Row Address

  for (i = 0;i<MAX_ROW;i++){
    for (j = 0;j<MAX_COL/2;j++){
      Write_Data(ptr[i][j]);
    }
  }
}




unsigned char pic1 [MAX_ROW][MAX_COL/2]= {

0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X 
00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X 
00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X .......

von Crazy Harry (crazy_h)


Angehängte Dateien:

Lesenswert?

Das Display sieht aus, wie das EA W128128-XR und so eines hab ich hier 
laufen.
Schau dir mal die Beschaltung des EA-Displays an.

EA: Vcc Pin2 >12.5V ;-)

Init hab ich auch noch:
1
Procedure GraphInit;                             // Init W128128
2
  Begin
3
    OLEDRst:=0;                                  // /Reset
4
    MDelay(100);
5
    OLEDRst:=1;                                  // Reset
6
    MDelay(100);
7
8
    WriteLCD($A4,false);                         // Set normal display mode
9
    WriteLCD($81,false);                         // Set contrast ...
10
    WriteLCD($7F,false);                         // ... to $7F
11
    WriteLCD($B3,false);                         // Ser clock divider/oscillator frequency ...
12
    WriteLCD($40,false);                         // ... to 64
13
    WriteLCD($AF,false);                         // Display on
14
    WriteLCD($A0,false);                         // Set memory addressing mode ...
15
    WriteLCD(%01010001,false);                   // A = COM Split
16
           // 0A0B0CDE                           // B = COM remap
17
                                                 // C = 0:horiz.incr. 1:vert.incr.
18
                                                 // D = Nipple remap
19
                                                 // E = Column remap
20
    WriteLCD($A1,false);                         // Set display start line ...
21
    WriteLCD($00,false);                         // ... to 0
22
    WriteLCD($A2,false);                         // Set display offset ...
23
    WriteLCD($00,false);                         // ... to 0
24
    WriteLCD($2E,false);                         // Deactivate scroll
25
26
    MDelay(50);
27
  End GraphInit;

WriteLCD schreibt ein Byte über SPI. "false" heißt als Command-Byte 
(true wäre ein Datenbyte).


Dein "Datenblatt" zum Display hat den Namen nicht verdient --> Mist!

Was hast du für eine Buchse genommen? Da gibts nämlich bottom up und 
bottom down, je nachdem wo die Kontakte liegen. Bei der falschen Buchse 
gibts keinen Kontakt.

: Bearbeitet durch User
Beitrag #5906115 wurde vom Autor gelöscht.
von Crazy Harry (crazy_h)


Lesenswert?

Hast du den Reset auch am Controller oder fest auf +Ub?

Und, wie erwähnt, hast du die richtige Buchse?

Mach mal vor und nach dem /CS eine Pause (bei mir reicht ein NOP) rein.
1
Procedure WriteLCD(Arg:Byte;IsData:Boolean);
2
  Begin
3
    If IsData=true
4
      then
5
        PortC:=PinC or %00000100;                // Daten PortC,2
6
        NOP;                                     // ohne das gehts nicht
7
      else
8
        PortC:=PinC and %11111011;               // Befehl
9
        NOP;                                     // ohne das gehts nicht
10
      EndIf;
11
    PortC:=PinC and %11101111;                   // /CS PortC,4
12
    SPIOutByteC(Arg);                            // Output arg
13
    PortC:=PinC or %00010000;                    // CS
14
  End WriteLCD;

: Bearbeitet durch User
von Flor B. (florben)


Lesenswert?

Ja, das ist so ziemlich das selbe Display.
Das Display ist genau so angeschlossen wie auf deinem Anschlussplan.
VCC ist bei mir natürlich nicht 5V sondern 15V (vertippt).

"WriteLCD schreibt ein Byte über SPI. "false" heißt als Command-Byte
(true wäre ein Datenbyte)."
So hatte ich das auch aus dem Datenblatt gelesen und eigentlich auch 
umgesetzt.

"Dein "Datenblatt" zum Display hat den Namen nicht verdient --> Mist!"
Da stimme ich Komplet zu :).

"Was hast du für eine Buchse genommen? Da gibts nämlich bottom up und
bottom down, je nachdem wo die Kontakte liegen. Bei der falschen Buchse
gibts keinen Kontakt."

Welche Buchse meinst du? Die FPC Buchse des Displays?

Leider bisher alles ohne Erfolg.
Das Display bleibt dunkel.

von Crazy Harry (crazy_h)


Angehängte Dateien:

Lesenswert?

Flor B. schrieb:
> Welche Buchse meinst du? Die FPC Buchse des Displays?

genau. Meine Platine liegt hinten auf dem Display drauf, d.h. der 
Flexleiter ist nach hinten umgebogen und die Kontakte sind unten (hab 
ich mich vorhin getäuscht) --> bottom contact Buchse (nicht bottom up).
Würdest du z.B. die Platine waagerecht hinter das Display montieren, so 
daß der Flexleiter auf der anderen Platinenseite ist, bräuchtest du eine 
top contact Buchse.

: Bearbeitet durch User
von Crazy Harry (crazy_h)


Angehängte Dateien:

Lesenswert?

falls es dich interessiert .....

Schreib mal lauter $FF in den Displayspeicher. Vielleicht liegen die 
paar Punkte die du setzt alle in den Ecken und runde Displays haben 
keine ;-)

: Bearbeitet durch User
von Flor B. (florben)


Lesenswert?

>Und, wie erwähnt, hast du die richtige Buchse?

Ich nutze aktuell ein Breakoutboard, die Pinbelegung passt.

>Schreib mal lauter $FF in den Displayspeicher. Vielleicht liegen die
paar Punkte die du setzt alle in den Ecken und runde Displays haben
keine ;-)

In meiner Ausgabefunktion ist leider noch ein Fehler (Wie oben 
geschrieben).
Aber die Displaydaten sollten passen. Das sie bereits auf einem 
Baugleichen Dsipay ausgegeben wurden.

von Flor B. (florben)


Lesenswert?

Crazy H. schrieb:
> falls es dich interessiert .....
>
> Schreib mal lauter $FF in den Displayspeicher. Vielleicht liegen die
> paar Punkte die du setzt alle in den Ecken und runde Displays haben
> keine ;-)

Wie hast du das mit der Displayausgabe (Ausgabefunktion) gelöst?
Ich komme hier einfach nicht weiter...

von Crazy Harry (crazy_h)


Lesenswert?

Hallo Flor,

dazu müßtest du mir sagen, wie dein Compiler grafische Displays 
behandelt.
Hast du im RAM ein Displayabbild und überträgst es mit einer 
Refresh-Funktion zum Display oder arbeitest du direkt im Display?
Bei mir ist ersteres der Fall.

Harry

von Flor B. (florben)


Lesenswert?

Hallo Harry,

bei mir wäre auch ersteres der Fall.

Bisher habe ich das mit der Funktion Pic-Show lösen wollen.
An die Funktion übergebe ich einfach die auszugeben Bildschirmdaten.
In diesem Fall die Daten pic1.

Leider funktioniert der Übergabeparameter nicht.




 int main(void)
{

    Pic_show(&pic1);// Ausgabe an Display
}




void Pic_show(unsigned char ptr[][MAX_COL/2]){
  unsigned char i=0,j=0;

  Write_Cmd(0x15);  //Set Column Address
  Write_Cmd(0x00);  //Start Column Address
  Write_Cmd(0x3F);  //End Column Address

  Write_Cmd(0x75);  //Set Row Address (segment)
  Write_Cmd(0x00);  //Satrt Row Address
  Write_Cmd(0x7F);  //End Row Address

  for (i = 0;i<MAX_ROW;i++){
    for (j = 0;j<MAX_COL/2;j++){
      Write_Data(ptr[i][j]);
    }
  }
}



unsigned char pic1 [MAX_ROW][MAX_COL/2]= {

0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X
00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X
00,0X00,
0X00,0X00,0X00,0X00,0X00,0X00,0X00,0X .......

von Crazy Harry (crazy_h)


Lesenswert?

Hallo Flor,

bei mir sieht das so aus:
1
UserDevice GraphIOS(Cmd:Byte;Arg:Byte);          // Cmd=0 --> Page
2
  Begin                                          // Cmd=1 --> Daten
3
    If Cmd=0                                     // nur einmalige Adressierung
4
      then                                       // notwendig
5
        If Arg=0
6
          then
7
            WriteLCD($15,false);                 // Set column address
8
            WriteLCD($00,false);                 // Start address
9
            WriteLCD($3F,false);                 // End address
10
            WriteLCD($75,false);                 // Set page address
11
            WriteLCD($00,false);                 // Start address
12
            WriteLCD($7F,false);                 // End address
13
          EndIf;
14
      else
15
        DispData[0]:=DispMap[((Arg and $C0) SHR 6)];  // Umwandlung sw --> 4-Bit Graustufen
16
        DispData[1]:=DispMap[((Arg and $30) SHR 4)];
17
        DispData[2]:=DispMap[((Arg and $0C) SHR 2)];
18
        DispData[3]:=DispMap[ (Arg and $03)       ];
19
20
        For iCounter:=0 to 3 do                       // Ausgabe 8 Pixel
21
          WriteLCD(DispData[iCounter],true);
22
          EndFor;
23
      EndIf;
24
  End GraphIOS;

Ja richtig erkannt, kein C.
Daß das ein Graustufencontroller ist, weißt du?
DispData ist bei mir einfach nur ein Array[0..3] of Byte und dient der 
Konvertierung s/w --> grau

Gruss
Harry

vergessen:

Const
  DispMap         : Array[0..3] of Byte = ($00,$0F,$F0,$FF);

Schick doch einfach mal nach der Zeilen-/Spaltenaddressierung 8192 $FF 
raus, dann muß das Display vollständig eingeschaltet sein, oder du 
schaltest beim Init auf invers um, dann muß es auch vollständig 
eingeschaltet sein. Wenn das nicht geht, ist was anderes faul.

..... noch was: mein Displayspeicher ist ein Array[0..2047] of Byte. Ein 
Bit=ein Pixel.

: Bearbeitet durch User
von Flor B. (florben)


Lesenswert?

Hallo Harry,

das Display funktioniert nun:).

Mit der Umwandlung der BMP-Datei tue ich mir aber noch etwas schwer.

Ich brauche ja einen 8bit Wert für jedes Pixel.
Die meisten Programme die BMP-Dateien Wandeln machen das aber mit 
8Pixel/byte.

Wie machst du das?

Gruß

Flor

von Crazy Harry (crazy_h)


Lesenswert?

Hi Flor,

sorry grad erst gesehen .... deine Frage wurde bereits beantwortet, aber 
gerne nochmal:
1
        DispData[0]:=DispMap[((Arg and $C0) SHR 6)];  // Umwandlung sw --> 4-Bit Graustufen
2
        DispData[1]:=DispMap[((Arg and $30) SHR 4)];
3
        DispData[2]:=DispMap[((Arg and $0C) SHR 2)];
4
        DispData[3]:=DispMap[ (Arg and $03)       ];
5
6
        For iCounter:=0 to 3 do                       // Ausgabe 8 Pixel
7
          WriteLCD(DispData[iCounter],true);
8
          EndFor;
DispData : Array[0..3] of Byte;
Arg sind die Display-Daten in sw.

Harry

: Bearbeitet durch User
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.