mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Newbie Probleme bei LCD DOGM Initialisierung in Assembler


Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich arbeite mich langsam durch das AVR Tutorial.
Mit dem LCD habe ich nun arge Probleme und suche hier Hilfe.
Habe mir ein DOGM163S-A bestellt und bin nun seit Tagen am verzweifeln.

Das Thema wurde schon vielfach besprochen. Habe lange im Forum
gelesen, trotzdem finde ich meinen Fehler nicht.
Wäre nett, wenn jemand meinen Code ansehen könnte, um mir einen
Tipp zu geben.

Ich Programmiere im AVR Studio in Assembler. C-Code verstehe ich noch 
nicht.
Habe einen ATmega8 auf einem STK600, ext. Takt ca. 4MHz.

Das LCD habe ich wie im Datenblatt für 5V 4-Bit beschaltet.
R/W ziehe ich auf GND und Reset auf +5V.
D4-D7 habe ich auf PORTD0-3, RS auf PORTD4 und E auf PORTD5 gelegt.
So wird es im Tutorial ja auch beschrieben.
Hintergrundbeleuchtung ist C1/C2 A1/A2 parallel mit ca. 33 Ohm 
Vorwiderstand an 5V. Das ist das einzige, was funktioniert :)
Auf dem LCD tut sich absolut überhaupt nichts.

Vielleicht könnte auch jemand ein .hex zur Verfügung stellen,
damit ich einen Hardware Fehler / Fehler bei der Beschaltung 
ausschließen kann?
Habe das Initialiesierungsprotokoll des Datenblatts versucht umzusetzen. 
Meist findet sich ja hier oder in den Timings der Fehler, aber ich finde 
es nich. In der Simulation mit AVR Studio sieht es eigentlich auch gut 
für mich aus.

Kann mir bitte jemand helfen. Das frustet mich.

Gruß Marcus
.include "m8def.inc"

ldi r16,LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
out SPL, r16
ldi r16,HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
out SPH, r16

ldi r16, 0xFF  
out DDRD, r16        //Port D = Ausgang

rcall  LCD_init
rcall  LCD_clear

          ldi r16, $45     ; Zeichen anzeigen
           rcall lcd_data
 
loop:
           rjmp loop

; Daten an LCD senden
LCD_data:
mov r17,r16          //r17 in r16 kopieren
swap r16          //oberes gegen unteres Nibble tauschen
andi r16, 0b00001111    //nur das untere übernehmen
sbr r16,0b00010000      //RS (PORT D4) auf high
out PORTD, r16        //erstes Nibble wurde übertragen
rcall LCD_enable

andi r17, 0b00001111    //zweites Nibble (r17), nur das untere übernehmen
sbr r17, 0b0001000      //RS (PORT D4) auf high
out PORTD, r17
rcall LCD_enable
rcall delay26us
ret

;Einen Befehl ausführen (ohne sbr r16,1<<4 (RS auf low))
LCD_command:
mov r17,r16          //r17 in r16 kopieren
swap r16          //oberes gegen unteres Nibble tauschen
andi r16, 0b00001111    //nur das untere übernehmen
out PORTD, r16        //erstes Nibble wurde übertragen
rcall LCD_enable

andi r17, 0b00001111    //zweites Nibble (r17), nur das untere übernehmen
out PORTD, r17
rcall LCD_enable
rcall delay26us
ret

LCD_enable:
sbi PORTD, 5        //enable high
nop              //3 Taktzyklen warten
nop
nop
cbi PORTD, 5        //enable wieder low
ret


;Delay Schleifen bei 4MHz Taktfrequenz
delay26us:                               ; 26,3us Pause
           ldi  r17, 5
WGLOOPA:   ldi  r18, 71
WGLOOPB:   dec  r18
           brne WGLOOPB
       dec  r17
           brne WGLOOPA
           ret                          ; wieder zurück
 
delay1600us:                               ; 1,6ms Pause
           ldi  r17, 12
WGLOOP0:   ldi  r18, 178
WGLOOP1:   dec  r18
           brne WGLOOP1
       dec  r17
           brne WGLOOP0
           ret                          ; wieder zurück

delay40ms:                               ; 40ms Pause
           ldi  r17, 230
WGLOOP0_:   ldi  r18, 250
WGLOOP1_:   dec  r18
           brne WGLOOP1_
       dec  r17
           brne WGLOOP0_
           ret                          ; wieder zurück
 
; LCD init EA DOGM163S-A VCC = 5V

LCD_init:
//wait time >40mS after VDD stable
           rcall  delay40ms
//Function set
       ldi r16,0b00000011
       out PORTD, r16
       rcall LCD_enable
//wait time >1,6mS
      rcall delay1600us
//Function set
       rcall LCD_enable  //2x
//wait time  >26.3uS
      rcall delay26us
//Function set
       rcall LCD_enable  //3x
//wait time  >26.3uS
      rcall delay26us
//Function set
       ldi r16,0b00000010 //4-Bit
       out PORTD, r16
       rcall LCD_enable
//wait time  >26.3uS
      rcall delay26us
//Function set
       ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1
       out PORTD, r16
       rcall LCD_command
//wait time  >26.3uS
      ;rcall delay50us
//Bias set
       ldi r16,0b00011101 //BS: 1/4, 3-zeiliges LCD
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      ;rcall delay50us
//Contrast Set
       ldi r16,0b01111100 //Konstrast C3, C2, C1 setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      ;rcall delay50us
//Power/ICON/Contrast control
       ldi r16,0b01010000 //Booster aus, Kontrast C5, C4 setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      ;rcall delay50us
//Follower control
      ldi r16,0b01101100 //Spannungsfolger und Verstärkung setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      ;rcall delay50us
//Display ON/OFF control
      ldi r16,0b00001111 //Display ein, Cursor ein, Cursor blinken
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      ;rcall delay50us      
      ret

LCD_clear:
      ldi r16,0b00000001 //Display löschen, Cursor Home
      out PORTD, r16
      rcall LCD_enable
      rcall delay26us      
      ret


Autor: Stefan B. (stefan) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcus Scholz schrieb:

> ...
> Habe einen ATmega8 auf einem STK600, ext. Takt ca. 4MHz.
> ...
> ;Delay Schleifen bei 4MHz Taktfrequenz
> ...

Dieser Sache würde ich als erstes nachgehen. Die Delay müssen stimmen, 
da hilft kein "ca.". Zur Not ein Blinkprogramm für'ne LED schreiben und 
den Puls des Kleinen messen...

Ein beliebtes Problem ist auch die Kontrasteinstellung des LCD. Link zum 
Datenblatt wäre vielleicht auch hilfreich, wenn andere das Timing 
überprüfen wollen/sollen.

Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Marcus Scholz schrieb:

> R/W ziehe ich auf GND und Reset auf +5V.

Wie z.B. hier beschrieben: 
Beitrag "DOGM132-5 mit SPI ansteuern" duerfte das Display einen 
ordentlichen Reset fuer die Initialisierung erwarten.

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei den DOGM musste sehr genau auf die Zeiten achten, die das Display 
zur Ausführung der Befehle braucht, z.B der Clear/REturn Home braucht in 
etwa 1 ms anstatt der bei dir erwähnten 26us.

Also ich fang bei ner Initialisierung immer so an, dass ich die 
Wartezeiten und Delays großzügig ausleg, damit man einfach sehr schnell 
ein funktionierendes Display hat.
Sobald es läuft kann man die Zeiten stückchenweiße reduzieren.
Auch die Enable-Zeit würd ich länger machen, vorm Enable kurz warten, 
dahinter auch wieder kurz warten.

Autor: Marcus Scholz (msohz)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


ersteinmal vielen Dank für die rege Unterstützung!!

Anbei poste ich die Datenblätter.

Die Timings werde ich mir noch genauer ansehen.

Mit den Delays habe ich Probleme gehabt, diese auszurechnen.
Habe so gerechnet: 4MHz, sind 25nS pro Takt. Dann benötige ich
1,6Mio. Takte für z.B. 40mS. Diesem Wert habe ich mich dann in der Delay 
Schleife angenähert. Dabei 3 Takte für 'brne' und 'dec' * der Anzahl der 
Durchläufe gerechnet. Diesen Wert dann ein weiteres Mal multipliziert 
mit der äußeren Schleife.

Wie wird das Richtig gemacht? Habt ihr einen Link, wo es genauer erklärt 
wird?

Werde einen weiteren Port schalten, der ein Reset sendet. Danke für den 
Tipp Peter. Meine Delays werde ich auch großzügiger auslegen.

Hoffentlich kann ich dann bald eine Erfolgsmeldung berichten.

Gruß Marcus

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Habe so gerechnet: 4MHz, sind 25nS pro Takt. Dann benötige ich...

Nee. 250ns

MfG Spess

Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

na dann sind die delays ja gar nicht zu knapp :)

-LOL- werde dass mal überarbeiten. Danke!

Gruß Marcus

Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das LCD bleibt leider ohne Reaktion.

Habe eure Vorschläge so gut ich kann umgesetzt:

Habe jetzt auf PORTB0 das RESET (PIN40) gelegt.

Anfangs ziehe ich es für 10ms auf high, dann für 100ms auf low und dann
belasse ich es auf high. Warte wieder 100ms und beginne dann mit der 
Initialisierung.

Die Timings zwischen den einzelnen Inits habe ich mal alle auf je 1ms
gesetzt. Dass ist doch mehr als genug, oder?

Könnt ihr mir noch weitere Tips geben, was ich falsch gemacht habe?

Danke nochmals.
Gruß Marcus

Anbei der geänderte Code:
.include "m8def.inc"

.EQU TAKT = 4001728    ;Systemtakt

ldi r16,LOW(RAMEND)      ; LOW-Byte der obersten RAM-Adresse
out SPL, r16
ldi r16,HIGH(RAMEND)     ; HIGH-Byte der obersten RAM-Adresse
out SPH, r16

ldi r16, 0xFF  
out DDRD, r16        //Port D = Ausgang
out DDRB, r16

rcall  LCD_init
rcall  LCD_clear

         ldi r16, $45     ; Zeichen anzeigen
         rcall lcd_data
 
loop:
         rjmp loop

; Daten an LCD senden
LCD_data:
mov r17,r16          //r17 in r16 kopieren
swap r16          //oberes gegen unteres Nibble tauschen
andi r16, 0b00001111    //nur das untere übernehmen
sbr r16,0b00010000      //RS (PORT D4) auf high
out PORTD, r16        //erstes Nibble wurde übertragen
rcall LCD_enable

andi r17, 0b00001111    //zweites Nibble (r17), nur das untere übernehmen
sbr r17, 0b0001000      //RS (PORT D4) auf high
out PORTD, r17
rcall LCD_enable
ldi r16, 1
rcall warte1ms
ret

;Einen Befehl ausführen (ohne sbr r16,1<<4 (RS auf low))
LCD_command:
mov r17,r16          //r17 in r16 kopieren
swap r16          //oberes gegen unteres Nibble tauschen
andi r16, 0b00001111    //nur das untere übernehmen
out PORTD, r16        //erstes Nibble wurde übertragen
rcall LCD_enable

andi r17, 0b00001111    //zweites Nibble (r17), nur das untere übernehmen
out PORTD, r17
rcall LCD_enable
ldi r16,1
rcall warte1ms
ret

LCD_enable:
sbi PORTD, 5        //enable high
nop              //3 Taktzyklen warten
nop
nop
nop
nop
cbi PORTD, 5        //enable wieder low
nop
nop
nop
ret


;Delay Schleifen
warte1ms:
      push r24
      push r25
      ldi r24, LOW(TAKT/4000)    ;4MHz ergibt 1000
      ldi r25, HIGH(TAKT/4000)  ;1 Takt ist hier 250ns
warte1ms_:  sbiw r24,1          ;subtrahiere 1 (2-Takte)
      brne warte1ms_        ;2-Takte
      nop              ;bis hier (4000 Takte = 1000000 ns)
      pop r25
      pop r24
      ret

wartex10ms:                ;wartet 10ms * Faktor aus r16
      push r16
      push r24
      push r25
wartex10msa:ldi r24, LOW(TAKT/400)  
      ldi r25, HIGH(TAKT/400)  
wartex10msb:sbiw r24,1          ;subtrahiere 1 (2-Takte)
      brne wartex10msb      ;2-Takte
      dec r16            ;Zähler vermindern
      brne wartex10msa
      pop r25
      pop r24
      pop r16
      ret

 
; LCD init EA DOGM163S-A VCC = 5V

LCD_init:
//RESET des ST7036
//PORTB0 ist Reset

    sbi PORTB , 0              ;RESET auf high
  
    //10ms warten
    ldi r16, 1
    rcall wartex10ms

    cbi PORTB , 0              ;RESET auf low

    //100ms warten
    ldi r16, 10
    rcall  wartex10ms
    
    sbi PORTB , 0              ;RESET auf high

//wait time >40mS after VDD stable
    ldi r16, 10
        rcall  wartex10ms
//Function set
       ldi r16,0b00000011
       out PORTD, r16
       rcall LCD_enable
//wait time >1,6mS
      rcall wartex10ms
//Function set
       rcall LCD_enable  //2x
//wait time  >26.3uS
      rcall warte1ms
//Function set
       rcall LCD_enable  //3x
//wait time  >26.3uS
      rcall warte1ms
//Function set
       ldi r16,0b00000010 //4-Bit
       out PORTD, r16
       rcall LCD_enable
//wait time  >26.3uS
      rcall warte1ms
//Function set
       ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1
       out PORTD, r16
       rcall LCD_command
//wait time  >26.3uS

//Bias set
       ldi r16,0b00011101 //BS: 1/4, 3-zeiliges LCD
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS

//Contrast Set
       ldi r16,0b01111100 //Konstrast C3, C2, C1 setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      
//Power/ICON/Contrast control
       ldi r16,0b01010000 //Booster aus, Kontrast C5, C4 setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      
//Follower control
      ldi r16,0b01101100 //Spannungsfolger und Verstärkung setzen
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      
//Display ON/OFF control
      ldi r16,0b00001111 //Display ein, Cursor ein, Cursor blinken
       out PORTD, r16
       rcall LCD_command
//wait time >26.3uS
      
      ret

LCD_clear:
      ldi r16,0b00000001 //Display löschen, Cursor Home
      out PORTD, r16
      rcall LCD_enable
      rcall warte1ms
      ret


Autor: P. S. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was hast du mit CSB gemacht, fest auf low?

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>andi r17, 0b00001111    //zweites Nibble (r17), nur das untere übernehmen
>sbr r17, 0b0001000      //RS (PORT D4) auf high
>out PORTD, r17

Fehler in der zweiten Zeile

>//Function set
> ldi r16,0b00100001 //4-Bit, 2 Zeilen, Instruction Table 1
> out PORTD, r16
> rcall LCD_command

Was soll die Ausgabe auf PortD?

MfG Spess

Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,


Peter, ja CSB ist fest auf low.

Spess, in der zweiten Zeile fehlte eine Null.
Gut gesehen! :) - Danke!
Die Ausgabe auf PORTD war Unsinn, da diese
über LCD_command vorgenommen wird. Habe ich auskommentiert.

Das LCD tut leider immernoch nichts.

Hoffe ihr werdet mir noch weiter helfen.


Gruß Marcus

Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

es klappt! Mehr oder weniger...

Das Display initialisiert.

Ich habe mit den Contrasteinstellungen noch rumgespielt.

Bei abgedunkeltem Raum, kann ich die Kästchen in den Zeilen erahnen,
sehe einen Cursor im dritten Feld blinken, im ersten einen Strich oben 
im
zweiten einen Strich unten.

Bei Reset des ATmega kann es sein, dass das LCD initialisiert, oder
auch nicht, muss man öfters probieren.

Wenn es dann klappt, sieht man manchmal auch einen Buchstaben.

Ist immerhin ein Anfang und ich kann weiter probieren. Jetzt weiß ich,
dass der Schaltungsaufbau stimmt und die Pinbelegung passt.

Ich werde berichten...
Bin euch sehr dankbar für die Unterstützung!

Gruß Marcus

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

>Ist immerhin ein Anfang und ich kann weiter probieren. Jetzt weiß ich,
>dass der Schaltungsaufbau stimmt und die Pinbelegung passt.

Überprüfe noch mal die deine Initialisierungswerte (habe ich nicht 
gemacht).
Evtl. auch mal im Datenblatt des Controllers (vom Displays) nachsehen.

MfG Spess

Autor: Marcus Scholz (msohz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

das LCD verhält sich wirklich sehr zickig.
Wenn die Initialisierung nach mehrfachem Reset dann mal funktioniert 
haben sollte, ist es sehr schlecht ablesbar. Die Kontrasteinstellungen 
wirken sich nur minimal auf das LCD aus.
Lediglich wenn ich Pin25 von 5V abnehme und offen lasse, ist es 
einigermassen gut lesbar. Aber das es so schlecht initialisiert nervt 
wirklich.
Leider kann ich nicht herausfinden, wo mein Fehler genau liegt.
Habe die Initialisierung aus dem Datenblatt des LCD benuntzt. 
Verschiedene
Einstellungen, Reihenfolgen und Timings probiert.
Auch mit den Parametern aus den diversen Forenbeiträgen scheint es nicht
wirklich zu funktionieren.

Habe mir jetzt erstmal ein anderes LCD bestellt, um mit dem Assembler 
Lernen weiter zu kommen. In der Hoffnung, dass es damit einfacher wird.

Jedenfalls bedanke ich mich nochmals für Eure Hilfe. Danke!

Gruß
Marcus

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.