Hallo Zusammen,
aktuell habe ich ein Bolymin OLED Grafikdisplay 128x64 (SSD1303) über 
SPI Schnittstelle in Betrieb genommen. Mittlerweile klappt auch alles so 
weit ganz gut.
Aktuell habe ich nur noch zwei Problemchen:
1. Es  wird nach dem Einschalten noch kurz das letzte Bild angezeigt, 
bevor die Initialisierung startet. Kann ich das noch irgendwie 
softwaremäßig verbessern oder müsste ich hier hardwaremäßig die 
Versorgungsspannung erst später zuschalten?
2. Die Löschung des gesamten Display dauert relativ lange, da ich hier 
jeden Pixel einzeln lösche. Gibt es irgendwie die Möglichkeit dies über 
Initialisierungsbefehle schneller zu erledigen?
Vielen Dank schonmal im voraus. Anbei noch meine aktuelle 
Initialisierungsroutine.
Besten Dank,
Sascha
 1  | Init_LCD:
  |  2  |    
  |  3  |   wdr
  |  4  | 
  |  5  |   ldi   Merker,$AE                       ; Set Display (AF=ON , AE=OFF)
  |  6  |   call   Write_Instr  
  |  7  | 
  |  8  |   call  Display_Reset
  |  9  | 
  |  10  |   ldi   Merker,$40
  |  11  |   call  Write_Instr  
  |  12  |   ldi   Merker,$A0                       
  |  13  |   call  Write_Instr  
  |  14  |   ldi   Merker,$DA                      ; Set Pins Hardware
  |  15  |   call  Write_Instr                      
  |  16  |   ldi   Merker,$12   
  |  17  |   call  Write_Instr
  |  18  | 
  |  19  |   ldi   Merker,$C8                    
  |  20  |   call  Write_Instr  
  |  21  | 
  |  22  |   ldi   Merker,$A8                       ; Set Multiplex Ratio
  |  23  |   call  Write_Instr                       
  |  24  |   ldi   Merker,$3F
  |  25  |   call  Write_Instr
  |  26  | 
  |  27  |   ldi   Merker,$D5                       ; Set Clock Divide
  |  28  |   call  Write_Instr                         
  |  29  |   ldi   Merker,$40
  |  30  |   call  Write_Instr 
  |  31  | 
  |  32  |   ldi   Merker,$DB                       ; VCOM Deselect Level
  |  33  |   call  Write_Instr                         
  |  34  |   ldi   Merker,$40
  |  35  |   call  Write_Instr 
  |  36  | 
  |  37  |   ldi   Merker,$D9                       ; Discharge period
  |  38  |   call  Write_Instr                       
  |  39  |   ldi   Merker,$1F                       ; 
  |  40  |   call  Write_Instr 
  |  41  | 
  |  42  |   ldi   Merker,$D3                       ; Set Display Offset
  |  43  |   call  Write_Instr                   
  |  44  |   ldi   Merker,$00                      
  |  45  |   call  Write_Instr 
  |  46  | 
  |  47  |   ldi   Merker,$40                      ; Set Display Start Line
  |  48  |   call  Write_Instr  
  |  49  | 
  |  50  |   ldi   Merker,$A4                       ; A4=ON
  |  51  |   call  Write_Instr                     
  |  52  | 
  |  53  |   ldi   Merker,$A6                       ; Normal Display
  |  54  |   call  Write_Instr  
  |  55  | 
  |  56  |   ldi   Merker,$81                       ; Set Contrast Control
  |  57  |   call  Write_Instr
  |  58  |   ldi   Merker,$FF                      ; 0-255
  |  59  |   call  Write_Instr    
  |  60  | 
  |  61  |   ldi   Merker,$AD                       ; Set DC-DC
  |  62  |   call  Write_Instr                       
  |  63  |   ldi   Merker,$8A                       ; 8B=ON, 8A=Off
  |  64  |   call  Write_Instr   
  |  65  | 
  |  66  |   call  Pause_10ms
  |  67  | 
  |  68  |   ldi   Merker,$AF                       ; Set Display (AF=ON , AE=OFF)
  |  69  |   call  Write_Instr                                    
  |  70  |   call  pause_10ms
  |  71  |   ret
  |  72  | 
  |  73  | ; -------------------------------------------------------------------------
  |  74  | 
  |  75  | Display_Reset:   
  |  76  |   wdr 
  |  77  |   sbi   PortC,6                        ; D/C (H:Data; L: Command) 
  |  78  |   sbi   PortC,5                        ; CS  
  |  79  |   call  Pause_1ms    
  |  80  |   sbi   PortC,4
  |  81  |   call  Pause_10clk
  |  82  |   cbi   PortC,4
  |  83  |   call  Pause_1ms
  |  84  |   sbi   PortC,4
  |  85  |   call  Pause_200ms
  |  86  |   ret
  |  
  
   
  
  
 
      
      
  
  
  
   
  
  
      @ Sascha T. (ernie1973)
>1. Es  wird nach dem Einschalten noch kurz das letzte Bild angezeigt,
>bevor die Initialisierung startet. Kann ich das noch irgendwie
>softwaremäßig verbessern
Möglicherweise muss man so zeitig wie möglich bei der Initialisierung 
das Display per Befehl abschalten.
Set Display ON/OFF
> 2. Die Löschung des gesamten Display dauert relativ lange,
Wie lange?
>da ich hier
>jeden Pixel einzeln lösche.
Wie genau? Eingentlich muss man nur einmal die Adresse 0 setzen und dann 
132 x 64 Bit = 8448 Bit = 1056 Bytes schreiben. Der Adresszähler wird 
automatisch hochgezählt. Das LCD verträgt maximal 4 MHz SPI-Takt, macht 
für 1056 Bytes 2,1 ms. Sprich, man kann es pro Sekunde ca. 473 mal 
löschen. Reicht das nicht?
Poste vollständigen Code als Anhang, dann kann man dir helfen. 
   
  
  
 
      
      
  
  
  
   
  
  
      Vielen Dank für die Hinweise.
Ich habe jetzt mal in der Routine laut Anhang alle Pixel nacheinander 
beschrieben und es geht sehr schnell, sa dass man die Verzögerung nicht 
mehr merkt. Zuvor habe ich es über meinen Zeichenroutine mit einem 
leeren Zeichen gemacht, das hat dann deutlich länger gebraucht und man 
hat den Löschvorgang halt "gesehen", wenn das Display während dessen 
aktiviert war.
Bei der u.a. Routine habe ich nur das merwürdig Verhalten, dass ich eine 
Spalte mehr löschen muss. Annsonsten wird beim zweiten Durchlauf die 
letzte Spalte nicht gelöscht, aber dann komischerweise beim dritten. Am 
Ende bleibt aber die allerletzte Spalte ungelöscht! Mit den 129 
Durchläufen funkioniert es aber!
Bezüglich des Einschalten schalte ich das Display ja in der Init sofort 
aus, welche kurz nach den Portdefinitionen im Hauptprogramm durchgeführt 
wird. Man kann aber das alte Bild nur sehen, wenn das Gerät nach dem 
Abschalten relativ schnell wieder eingeschaltet wird. Wartet man 10s 
nach dem Ausschalten sieht man auch kein Bild mehr!
 1  | LCD_Clear:
  |  2  |   wdr  
  |  3  | 
  |  4  |   ldi   Merker,$AE                      ; Set Display (AF=ON , AE=OFF)
  |  5  |   call  Write_Instr  
  |  6  | 
  |  7  |   ldi   temp,$02                        ; Setze auf erste Spalte
  |  8  |   sts   sSpalteLow,temp
  |  9  |   ldi   temp,$10
  |  10  |   sts   sSpalteHigh,temp
  |  11  | 
  |  12  |   ldi   temp,$B0                        ; Lösche erste Zeile
  |  13  |   sts   sZeile,temp
  |  14  |   call  LCD_Clear_Zeile
  |  15  | 
  |  16  |   ldi   temp,$B1
  |  17  |   sts   sZeile,temp
  |  18  |   call  LCD_Clear_Zeile
  |  19  | 
  |  20  |   ldi   temp,$B2
  |  21  |   sts   sZeile,temp
  |  22  |   call  LCD_Clear_Zeile
  |  23  | 
  |  24  |   ldi   temp,$B3
  |  25  |   sts   sZeile,temp
  |  26  |   call  LCD_Clear_Zeile
  |  27  | 
  |  28  |   ldi   temp,$B4
  |  29  |   sts   sZeile,temp
  |  30  |   call  LCD_Clear_Zeile
  |  31  |   
  |  32  |   ldi   temp,$B5
  |  33  |   sts   sZeile,temp
  |  34  |   call  LCD_Clear_Zeile
  |  35  | 
  |  36  |   ldi   temp,$B6
  |  37  |   sts   sZeile,temp
  |  38  |   call  LCD_Clear_Zeile
  |  39  |   
  |  40  |   ldi   temp,$B7
  |  41  |   sts   sZeile,temp
  |  42  |   call  LCD_Clear_Zeile     
  |  43  |   
  |  44  |   ldi   Merker,$AF                       ; Set Display (AF=ON , AE=OFF)
  |  45  |   call  Write_Instr  
  |  46  |   ret
  |  47  | 
  |  48  | ; Löscht eine Zeile
  |  49  | LCD_Clear_Zeile:                        ; Die Routine muss aktuell einmal mehr durchlaufen werden, da ansonsten beim zweiten
  |  50  |   wdr                                   ; Aufruf die letzte Spalte nicht direkt beschrieben wird, sondern erst beim nächsten Durchlauf   
  |  51  | 
  |  52  |   lds   Merker,sSpalteLow
  |  53  |   call  Write_Instr
  |  54  |   lds   Merker,sSpalteHigh
  |  55  |   call  Write_Instr
  |  56  |   lds   Merker,sZeile
  |  57  |   call  Write_Instr
  |  58  | 
  |  59  |   ldi   temp,129
  |  60  |   sts   sMerker,temp
  |  61  | 
  |  62  | LCD_Clear_Zeile_Schleife:                      
  |  63  |   wdr                      
  |  64  |   ldi   Merker,$00
  |  65  |   call  write_data
  |  66  |   lds   temp,sMerker
  |  67  |   dec   temp
  |  68  |   sts   sMerker,temp
  |  69  |   cpi   temp,0
  |  70  |   brne  LCD_Clear_Zeile_Schleife
  |  71  |   ret
  |  
  
   
  
  
 
      
      
  
  
  
   
  
  
      Also idealerweise schaltet man OLED Displays so an und aus:
http://www.farnell.com/datasheets/303159.pdf
Seite 17
Das geht bei dir aber nicht, da der Spannungswandler fuer das Panel mit 
an Board ist.
Du koenntest beim Abschalten den Inhalt loeschen. 
   
  
  
 
      
      
  
  
  
   
  
  
      @Sascha T. (ernie1973)
>Ich habe jetzt mal in der Routine laut Anhang alle Pixel nacheinander
Keine Anhang, du hast den Querllcode in den Text kopiert. Naja, geht bei 
der Länge gerade noch so.
>beschrieben und es geht sehr schnell, sa dass man die Verzögerung nicht
>mehr merkt.
Ist aber noch viel Luft drin.
> Zuvor habe ich es über meinen Zeichenroutine mit einem
>leeren Zeichen gemacht, das hat dann deutlich länger gebraucht
Logisch.
>Bei der u.a. Routine habe ich nur das merwürdig Verhalten, dass ich eine
>Spalte mehr löschen muss. Annsonsten wird beim zweiten Durchlauf die
>letzte Spalte nicht gelöscht, aber dann komischerweise beim dritten. Am
>Ende bleibt aber die allerletzte Spalte ungelöscht! Mit den 129
>Durchläufen funkioniert es aber!
Hmm, ich verstehe sowieso nicht ganz die Speicherorganisation. Wie 
spricht man die 1k SPeicher an? Über Page und Coloum, klar, aber was 
gehört wie zusammen?
Egal. Deine Routine kann man noch um einiges verbessern.
1. Nutze eine Schelife, um die 8 Pages einzustellen und zu löschen.
2. Eine Schleife, die sehr oft möglichst schnell durchlaufen werden 
soll, nutzt am Besten Register fpr Variablen und keinen SRAM. Ausserdem 
Kopiert man den Quelltext für den SPI-Zugriff hier direkt rein und macht 
keinen call, denn das dauert auch einige Takte. Und schmeiß diesen WDR 
raus, der nervt.
 1  |   ldi   r16,129   // Zähler
  |  2  |   ldi   r17,0   // Leer-Daten
  |  3  | LCD_Clear_Zeile_Schleife:                      
  |  4  |   sbis  spcr, spif
  |  5  |   rjmp  LCD_Clear_Zeile_Schleife
  |  6  |   out   spdr, r17
  |  7  |   dec   r16
  |  8  |   brne  LCD_Clear_Zeile_Schleife
  |  9  |   ret
  |  
 
MFG
Falk 
   
  
  
 
      
      
  
  
  
   
  
  
      Wegen der 129 statt 128 Zugriffe.
Seite 17.
"During data writing, an additional NOP command should be inserted 
before the CS# goes high (Refer to Figure 6."
Wobei hier wohl das Commando 0xE3 gemeint ist, es gibt mehrere NOPs. 
   
  
  
 
      
      
  
  
  
   
  
  
      1  |   ldi   r16,129   // Zähler
  |  2  |   ldi   r17,0   // Leer-Daten
  |  3  |   sbi   portx, pdx  // D/C bit setzen
  |  4  | LCD_Clear_Zeile_Schleife:                      
  |  5  |   sbis  spsr, spif
  |  6  |   rjmp  LCD_Clear_Zeile_Schleife
  |  7  |   out   spdr, r17
  |  8  |   dec   r16
  |  9  |   brne  LCD_Clear_Zeile_Schleife
  |  10  | 
  |  11  |   ldi   r17,$E3   // NOP
  |  12  |   cbi   portx, pdx  // D/C bit loeschen
  |  13  | LCD_Clear_2:
  |  14  |   sbis  spsr, spif
  |  15  |   rjmp  LCD_Clear_2
  |  16  |   out   spdr, r17
  |  17  | 
  |  18  |   ret
  |  
  
   
  
  
 
      
      
  
  
  
   
  
  
      Frank M. schrieb:
> Also idealerweise schaltet man OLED Displays so an und aus:
> http://www.farnell.com/datasheets/303159.pdf
> Seite 17
>
> Das geht bei dir aber nicht, da der Spannungswandler fuer das Panel mit
> an Board ist.
Ja, das wäre wohl besser. Ich habe halt gedacht, ob ich es irgendwie 
durch den Hardware Reset oder einen Software Befehl wie z.B. den "Set 
DC-DC" hinbekomme. Das klappt aber nicht.
> Du koenntest beim Abschalten den Inhalt loeschen.
Das wäre die sauberste Lösung, aber es geht bei dem Gerät leider nicht, 
da der Nutzer die Spannungsversorgung über eine Netzschalter trennen 
kann.
Aber vielen Dank für die Hilfestellung!
Gruß,
Sascha 
   
  
  
 
      
      
  
  
  
   
  
  
      Falk Brunner schrieb:
> Wegen der 129 statt 128 Zugriffe.
>
> Seite 17.
>
> "During data writing, an additional NOP command should be inserted
> before the CS# goes high (Refer to Figure 6."
>
> Wobei hier wohl das Commando 0xE3 gemeint ist, es gibt mehrere NOPs.
Vielen Dank für die Hinweise bezüglich der Löschroutine, das werde ich 
mal umsetzen.
Die o.a. Beschreibung halte ich eigentlich in meinen Schreibroutinen 
ein:
 1  | Write_Instr:
  |  2  |   wdr
  |  3  |   
  |  4  |   cbi   PortC,6          ; D/C (H:Data; L: Command) 
  |  5  |   cbi   PortC,5          ; CS
  |  6  |   nop
  |  7  |   nop
  |  8  |   call   SPI_Senden
  |  9  |   nop
  |  10  |   nop
  |  11  |   sbi   PortC,6          ; D/C (H:Data; L: Command) 
  |  12  |   sbi   PortC,5          ; CS
  |  13  |   ret
  |  14  | 
  |  15  | Write_Data:
  |  16  |   wdr
  |  17  | 
  |  18  | 
  |  19  |   sbi   PortC,6          ; D/C (H:Data; L: Command) 
  |  20  |   cbi   PortC,5          ; CS
  |  21  |   nop
  |  22  |   nop
  |  23  |   call   SPI_Senden
  |  24  |   nop
  |  25  |   nop
  |  26  |   sbi   PortC,6          ; D/C (H:Data; L: Command) 
  |  27  |   sbi   PortC,5          ; CS
  |  28  |   ret
  |  
  
   
  
  
 
      
      
  
  
  
   
  
  
      @ Sascha T. (ernie1973)
>Die o.a. Beschreibung halte ich eigentlich in meinen Schreibroutinen
>ein:
Defensiv und strukturiert programmierein ist ja gut, aber man kann es 
auch übertreiben. Schau dir mal an, wieviel Funtkionsaufrufe bei dir 
gemacht werden, ehe ein Byte über SPI raus geht! Und es reicht, VOR der 
Operation D/C zu setzen, danach kann es stehen bleiben wie es ist. 
   
  
  
 
      
      
  
  
  
   
  
  
      Falk Brunner schrieb:
> @ Sascha T. (ernie1973)
>
>>Die o.a. Beschreibung halte ich eigentlich in meinen Schreibroutinen
>>ein:
>
> Defensiv und strukturiert programmierein ist ja gut, aber man kann es
> auch übertreiben. Schau dir mal an, wieviel Funtkionsaufrufe bei dir
> gemacht werden, ehe ein Byte über SPI raus geht! Und es reicht, VOR der
> Operation D/C zu setzen, danach kann es stehen bleiben wie es ist.
Da magst Du Recht haben, aber die Struktur ist uns in der Entwicklung 
schon sehr wichtig und es hat ja im Grunde "nur" 
Geschwindigkeitseinbußen, die jetzt auch bei der neuen Löschroutine 
nicht mehr merkbar sind.
Teilweise sind es auch noch Überbleibsel aus der Inbetriebnahme des 
Displays, die aus diversen Gründen nicht so einfach war, so dass wir 
lieber noch etwas mehr gewartet haben oder den Port nochmal definiert 
haben, wie in dem geschilderten Fall.
Für das SPI benutzen wir aktuell auch noch eine Softwareschnittstelle, 
da die Hardware mal wieder anders belegt war. 
   
  
  
 
    
    
        
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
 
   
 
   
  
    
    
 
   |