Displaytec 162C mit KS0070B an Atmega16?

buhhh2002

Neues Mitglied
15. Mai 2009
26
0
0
Sprachen
Hallo Leute,
einen schönen guten Abend allerseits.
zuerst einmal bin neu im Forum sowie auch im Thema Mikrocontroller.

Hab zum anfangen ein STK 600 Board mit nem ATmega16 und 12Mhz Quarz und nem Displaytec162c (16x2) LCD mit beleuchtung von reichelt.
Schreiben tu ich mit avr studio 4.

Nach ein paar übungen bekomm ich mittlerweile Lauflichter und solche sachen hin :eek:

Nun wollt ich ein LCD im 4 bit mode ansteuern und hab es entsprechend verkabelt.
PD0 - PD3 an DB4 - DB7

und

RS an PD4 u E an PD5

Hab nun eine LCD routine draufgemacht und laufen lassen.
Da mein LCD eine getrennte Stomversorgung hat sieht man am Anfang in der ersten Zeile schwarze Balken... denk ist normal soweit.
Wenn jetzt AVR studio die übertragung beendet hat dann verschwinden der schwarze Balken und das Display bleibt leer.

Wenn ich nun drei mal (weiß nicht ob es zufall ist oder ob es immer drei mal sind) auf den Reset knopf drücke, wird auf einmal mein Text ausgegeben...

Wäre sehr nett wenn mir einer nen Denkanstoß geben würde oder am besten gleich die Lösung verrät :rolleyes:
 
Hallo ,

Hallo Leute,
einen schönen guten Abend allerseits.
zuerst einmal bin neu im Forum sowie auch im Thema Mikrocontroller.
dann mal herzlich willkommen hier im Forum ! :flowers:

Hab zum anfangen ein STK 600 Board mit nem ATmega16 und 12Mhz Quarz und nem Displaytec162c (16x2) LCD mit beleuchtung von reichelt.
Schreiben tu ich mit avr studio 4.
Was für ne Sprache verwendest Du denn ? Assembler , C oder Bascom ?


Nach ein paar übungen bekomm ich mittlerweile Lauflichter und solche sachen hin :eek:
Das ist doch schon mal was .. :)

Nun wollt ich ein LCD im 4 bit mode ansteuern und hab es entsprechend verkabelt.
PD0 - PD3 an DB4 - DB7

und

RS an PD4 u E an PD5
soweit scheint es schon mal OK zu sein (von der Portbelegung her).

Hab nun eine LCD routine draufgemacht und laufen lassen.
Da mein LCD eine getrennte Stomversorgung hat sieht man am Anfang in der ersten Zeile schwarze Balken... denk ist normal soweit.
Wenn jetzt AVR studio die übertragung beendet hat dann verschwinden der schwarze Balken und das Display bleibt leer.
Das mit den schwarzen Balken ist bei manchen Displays normal. Das ist wohl
so eine Art Test beim der Initialisierung. Das sollte aber bei jedem Start nach
der Initialisierung des Displays verschwinden.

Wenn ich nun drei mal (weiß nicht ob es zufall ist oder ob es immer drei mal sind) auf den Reset knopf drücke, wird auf einmal mein Text ausgegeben...
?? :confused: ?? Timing-Probleme ? Stimmt das Timing im Programm zum
Ansprechen des Displays nicht richtig ? Wär jetzt meine Idee.

Wäre sehr nett wenn mir einer nen Denkanstoß geben würde oder am besten gleich die Lösung verrät :rolleyes:
Dafür solltest Du uns aber wenigstens die Sprache nennen, die Du
verwendest. Und ein paar Codezeilen (am besten das Programm als Anhang)
wären auch nicht schlecht. Wir können zwar schon viel aber zum Hellsehen
reicht es noch nicht ;) :D

Gruß
Dino
 
Was für ne Sprache verwendest Du denn ? Assembler , C oder Bascom ?
Er hat ja geschrieben dass er seine Programme mit AVR Studio schreibt. Also kann es nur C oder Assembler sein.:)



Ich würde mal tippen dass der Displaycontroller nicht immer genug Zeit für die Initialisation hat. Probier mal am Anfang, Zwischendrin und villeicht noch am Schluss ein paar Delays reinzuprogrammieren. Also gleich am Anfang mal eine Sekunde Pause.
 
Sorry hab ich vergessen zu schreiben ich verwende assembler.
Hab meine LCD routine und das Testprogramm als anhang eingefügt...

Ich vermute auch das was mit der Zeit nicht stimmt aber wie gesagt bin anfänger und weiß nicht wo ich suchen soll
 

Anhänge

  • lcd-routine.txt
    8,1 KB · Aufrufe: 28
  • main LCD.txt
    1,3 KB · Aufrufe: 18
Hallo und willkommen im AVR-PRAXiS-Forum.

Das Assemblerprogramm ist für 12MHz ausgelegt, hast du den Takt auch? Wenn nicht, dann in lcd_routine den Wert für XTAL (ziemlich weit oben) anpassen.

Grüße,
Dirk
 
Hallo,

ich hab mal das "lcd-routine.txt" überflogen. Die Timings scheinen zu passen.
Aber so wie es aussieht paßt die Initialisierung nicht mit dem Datenblatt
überein. Sieh mal hier ...

KS0070b_4Bit_1.gif
KS0070b_4Bit_2.gif

Leider ist das Datenblatt des Controllers mit 547k zu groß zum hochladen :(
Kannst es dir ja selber mal ziehen.
Ich nehme eigentlich immer die Datenblätter der Controller und nicht die des
LCD-Displays. Da steht nämlich manchmal nur was mit soundso-Kompatibel.
Aber so kompatibel sind die dann manchmal leider doch nicht.

Als Tip ... grenz dir die Subroutinen besser voneinander ab. Dann wird das
alles leserlicher und schneller zu überblicken.

Das sind meine Routinen für nen ST7066U (bei Pollin Display PC1602).
Auch mit 4Bit-Mode. Sieh dir das mal an (nur mal als Anregung) ...



CodeBox ASM

; ##################################################################
; ##################################################################
; #### LCD-Subroutinen #############################################
; ##################################################################
; ##################################################################

; ==================================================================
; ===== LCD initialisieren (4-Bit-Modus) ===========================
; ==================================================================
lcdinit:
push r16 ; r16 auf Stack retten (fuer wiederherstellung)

cbi portb,5 ; RS (PB5) loeschen => E loeschen
cbi portb,4 ; RS (PB4) loeschen => Cmd

; Powertip PC1602-E 16x2 Chr , Controller ST7066U
; 4-Bit-Modus ( D4-7 , D0-3 )
;
; === 4-Bit Init ===
; RS RW D7654 - RS 0=Cmd 1=Data , RW 0=Wr 1=Rd
; - wait >40ms
;
; - RS:0 RW:0 0b 0011 (0x3)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (1)
; - RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0010 (0x2) - FunctionSet 4Bit (2)
; - RS:0 RW:0 0b NF** (0x8) - Lines,Font (N 0=1L 1=2L , F 0=5x8Dot)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0000 (0x0) - DisplaySet
; - RS:0 RW:0 0b 1DCB (0xC) - Display,Cursor,Blink (0=Off / 1=On)
;
; - wait >37us
;
; - RS:0 RW:0 0b 0000 (0x0) - Clear Display
; - RS:0 RW:0 0b 0001 (0x1)
;
; - wait >1,52ms
;
; - RS:0 RW:0 0b 0000 (0x0) - EntryMode
; - RS:0 RW:0 0b 01IS (0x6) - Inc/Dec,Shift (I 1=inc , S 0=NoShift)
;

ldi r16,7 ; 50ms ;
rcall waitx7m ; 7 x 7ms warten

; ===== 8-Bit =====
ldi r16,0x03 ; <=<=<=<=<=<=<=<= ### 0x3 ###
out portc,r16 ; Daten setzen (PC0-3 => D4-7) =0=
rcall wait580n ; >50ns warten
rcall lcdex ; EX pulsen zum uebernehmen (580ns)
rcall wait3m ; >37us warten


; * set function (SF) mode: 37us
; * Bit 0 : -
; * Bit 1 : -
; * Bit 2 : F: 0 = 5x8, 1 = 5x10 (Font)
; * Bit 3 : N: 0 = 1L, 1 = 2L (Display Lines)
; * Bit 4 : DL: 0 = 4Bit , 1 = 8Bit (Data Length)
; * Bit 5 : 1
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * 00101000 : SF, 4-bit mode, 2 lines, 5x8 Font
;
ldi r16,0x28 ; 00101000 Set Function Mode (SF)
rcall lcdcmd ; ausfuehren (erstes Mal)

ldi r16,0x28 ; 00101000 Set Function Mode (SF)
rcall lcdcmd ; ausfuehren (zweites Mal)


; * set display (SD) mode: 37us
; * Bit 0 : B: 0 = off , 1 = on (turn on character blinking)
; * Bit 1 : C: 0 = off , 1 = on (turn on cursor)
; * Bit 2 : D: 0 = off , 1 = on (turn on display)
; * Bit 3 : 1
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * SD: 0x20 = 00001100
; * SD: turn off display
; ldi r16,0b00100000 ; Set Display Mode (SD) 0x20
;
rcall lcdcmd ; ausfuehren
ldi r16,0x0C
rcall lcdcmd


; * clear and home (CH) : 1,52ms
; * CH: 0x01 = 00000001
; * CH: clear and home
; ldi r16,0b00000001 ; Clear and Home (CH) 0x01
;
ldi r16,0x01
rcall lcdcmd
rcall wait3m ; >1,52ms warten


; * set entry (SE) mode: 37us
; * Bit 0 : S: 0 = off , 1 = on (Display Shift)
; * Bit 1 : I/D: 0 = Dec , 1 = Inc (Crs/Dsp Move Direction)
; * Bit 2 : 1
; * Bit 3 : 0
; * Bit 4 : 0
; * Bit 5 : 0
; * Bit 6 : 0
; * Bit 7 : 0
; *
; * SE: 0x50 = 00000110
; * SE: increment display start after Write
;
ldi r16,0x06
rcall lcdcmd

pop r16 ; r16 wiederherstellen
ret ;



; ==================================================================
; ===== LCD-Befehl ausfuehren ======================================
; ==================================================================
lcdcmd: ; Befehl senden - Command in r16
; High Nibble zuerst, dann Low Nibble
push r17 ; r17 auf Stack retten (fuer wiederherstellung)

cbi portb,4 ; RS (PB4) loeschen => Cmd
swap r16 ; High Nibble nach unten
mov r17,r16 ; Daten zur Ausgabe kopieren
cbr r17,0xF0 ; Obere Bits loeschen

out portc,r17 ; Daten setzen High (PC0-3 => D4-7)
nop ; |
nop ; |
nop ; |250ns warten
nop ; |
nop ; |
rcall lcdex ; EX pulsen zum uebernehmen (580ns)
rcall wait580n ; 580ns warten

swap r16 ; Low Nibble zurueck nach unten
mov r17,r16 ; Daten zur Ausgabe kopieren
cbr r17,0xF0 ; Obere Bits loeschen

out portc,r17 ; Daten setzen Low (PC0-3 => D4-7)
pop r17 ; r17 wiederherstellen (2 Taktzyklen = 2 NOPs)
; nop ; |--->durch vorgezogenen pop ersetzt
; nop ; |--->durch vorgezogenen pop ersetzt
nop ; |250ns warten
nop ; |
nop ; |
rcall lcdex ; EX pulsen zum uebernehmen (580ns)

rcall wait26u ; >37us warten
rcall wait26u ;
ret ;


; ==================================================================
; ===== LCD-Execute pulsen =========================================
; ==================================================================
lcdex: ; E aktivieren (Befehlsuebergabe)
;
sbi portb,5 ; E (PB5) setzen
rcall wait580n ; >460ns warten
cbi portb,5 ; E (PB5) loeschen
ret ;





; ##################################################################
; ##################################################################
; #### Warte-Subroutinen ###########################################
; ##################################################################
; ##################################################################
; 62,5ns Zykluszeit bei 16MHz
; 50,0ns Zykluszeit bei 20MHz

; ==================================================================
; ===== 580ns warten ===============================================
; ==================================================================
; rcall wait580n ; (3) Warteschleife aufrufen
wait580n: ; 11 Cyclen (incl Call+Ret) => ~550ns@20MHz
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 750ns warten ===============================================
; ==================================================================
; rcall wait750n ; (3) Warteschleife aufrufen
wait750n: ; 15 Cyclen (incl Call+Ret) => ~750ns@20MHz
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
nop ; (1)
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 10us warten ================================================
; ==================================================================
; rcall wait10u ; (3) Warteschleife aufrufen
; ================> ; 200 Cyclen (incl Call+Ret) => ~10us@16MHz
wait10u: push r20 ; (2) r20 auf Stack retten
ldi r20,94 ; (1) Zaehler initialisieren 105 (14us) , 75 (10us) @16MHz
; 94 (10us) @20MHz
; 1__223__
; | |
; 1 Cycle = 105*2+1+12
loop10u: dec r20 ; (1) | niedrigstes Byte -1
brne loop10u ; (1f,2t)_/ 0 erreicht? nein -> Schleife

pop r20 ; (2) r20 zurueckholen
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 26us warten ================================================
; ==================================================================
; rcall wait26u ; (3) Warteschleife aufrufen
; ================> ; 525 Cyclen (incl Call+Ret) => ~26,5us@20MHz
wait26u: push r20 ; (2) r20 auf Stack retten
clr r20 ; (1) Zaehler initialisieren
;
; 1__513__
; | |
; 1 Cycle = 256*2+1+12
loop26u: dec r20 ; (1) | niedrigstes Byte -1
brne loop26u ; (1f,2t)_/ 0 erreicht? nein -> Schleife

pop r20 ; (2) r20 zurueckholen
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 516us warten ===============================================
; ==================================================================
; rcall wait516u ; (3) Warteschleife aufrufen
; ================> ; 10318 Cyclen (incl Call+Ret) => ~516us@20MHz
wait516u: push r20 ; (2) r20 auf Stack retten (1tes)
push r21 ; (2) r21 auf Stack retten (2tes)
clr r20 ; (1) r20+r21 ergeben zusammen
ldi r21,20 ; (1) einen 2-Byte-Zaehler (8241Cycl)
;
; 2________10318___
; | 1__513__ |
; | | | |
; 12 Cycle = 20*((256*2+1)+2)+1+17
loop516u: dec r20 ; (1) || niedrigstes Byte -1
brne loop516u ; (1f,2t)_/| 0 erreicht? nein -> Schleife
dec r21 ; (1) | mittleres Byte -1
brne loop516u ; (1f,2t)__/ 0 erreicht? nein -> Schleife

pop r21 ; (2) r21 zurueckholen (2tes)
pop r20 ; (2) r20 zurueckholen (1tes)
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 3ms warten =================================================
; ==================================================================
; rcall wait3m ; (3) Warteschleife aufrufen
; ================> ; 59758 Cyclen (incl Call+Ret) => ~3ms@20MHz
wait3m: push r20 ; (2) r20 auf Stack retten (1tes)
push r21 ; (2) r21 auf Stack retten (2tes)
clr r20 ; (1) r20+r21 ergeben zusammen
ldi r21,116 ; (1) einen 2-Byte-Zaehler (47913Cycl)
;
; 2__________59758__
; | 1__513__ |
; | | | |
; 12 Cycle = 116*((256*2+1)+2)+1+17
loop3m: dec r20 ; (1) || niedrigstes Byte -1
brne loop3m ; (1f,2t)_/| 0 erreicht? nein -> Schleife
dec r21 ; (1) | mittleres Byte -1
brne loop3m ; (1f,2t)__/ 0 erreicht? nein -> Schleife

pop r21 ; (2) r21 zurueckholen (2tes)
pop r20 ; (2) r20 zurueckholen (1tes)
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== 7ms warten =================================================
; ==================================================================
; rcall wait7m ; (3) Warteschleife aufrufen
; ================> ; 131858 Cyclen (incl Call+Ret) => ~6,59ms@20MHz
wait7m: push r20 ; (2) r20 auf Stack retten (1tes)
push r21 ; (2) r21 auf Stack retten (2tes)
clr r20 ; (1) r20+r21 ergeben zusammen
clr r21 ; (1) einen 2-Byte-Zaehler
;
; 2__________131841_
; | 1__513__ |
; | | | |
; 12 Cycle = 256*((256*2+1)+2)+1+17
loop7m: dec r20 ; (1) || niedrigstes Byte -1
brne loop7m ; (1f,2t)_/| 0 erreicht? nein -> Schleife
dec r21 ; (1) | mittleres Byte -1
brne loop7m ; (1f,2t)__/ 0 erreicht? nein -> Schleife

pop r21 ; (2) r21 zurueckholen (2tes)
pop r20 ; (2) r20 zurueckholen (1tes)
ret ; (4) Schleifenende, Rueckkehr


; ==================================================================
; ===== r16 * 7ms warten ===========================================
; ==================================================================
; rcall waitx7m ; (3) Warteschleife aufrufen - Zeit in r16
; ================> ; 131843*x+18 Cyclen (incl Call+Ret) => ~x*86,59ms@20MHz
waitx7m: push r20 ; (2) r20 auf Stack retten (1tes)
push r21 ; (2) r21 auf Stack retten (2tes)
clr r20 ; (1) r16, r20 und r21 ergeben
clr r21 ; (1) zusammen einen 3-Byte-Zaehler
; 3_____________________________
; r16=1 8,241ms min | 2____________131841_ |
; r16=0 2,109s max | | 1__513__ | |
; | | | | | |
; 123 Cycle = r16*((256*((256*2+1)+2)+1)+2)+1+17
loopx7m: dec r20 ; (1) ||| niedrigstes Byte -1
brne loopx7m ; (1f,2t)_/|| 0 erreicht? nein -> Schleife
dec r21 ; (1) || mittleres Byte -1
brne loopx7m ; (1f,2t)__/| 0 erreicht? nein -> Schleife
dec r16 ; (1) | höchstes Byte -1
brne loopx7m ; (1f,2t)___/ 0 erreicht? nein -> Schleife
;
pop r21 ; (2) r21 zurueckholen (2tes)
pop r20 ; (2) r20 zurueckholen (1tes)
ret ; (4) Schleifenende, Rueckkehr

Hier nochmal der ganze Kram ...
Anhang anzeigen TWI-1W-Analyzer.zip
läuft auf nem ATmega168 mit 20MHz. Die Aufrufe der Wait-Routinen haben
im Namen aber auch wie bei dir die Wartezeit drin.

Sieht bei dir aber auch schon recht nett aus was du da
zusammenprogrammiert hast :)

(Wau - der Text war zu lang ... Das Forum hat gemosert :rolleyes: :D )
naja, ist ja auch alles in der Zip.

Denn mal viel Spaß ... und erst mal das Datenblatt vom KS0070b runterziehen.
Da steht die gesamte Init drin. :D Leider hab ich da bei meinem auch erstmal
mächtig gestrickt. Dachte schon das Display oder die Verdrahtunng sind hin
oder falsch. Lies es dir im Internet als Anregung durch und dann mach es
nach dem Datenblatt. Dann läuft es auch ;) Im Internet ist leider nicht alles
richtig :eek:

Gruß
Dino
 
Was auch helfen kann, ist das LCD beim Flashen vom Strom zu trennen. Das LCD mit dem HD44780 Chip mag es scheinbar nicht am Strom zu hängen wenn man flasht. Jedenfalls ist diese Testpattern dann dauerhaft vorhanden :rolleyes:
 
LCD-Initialisierung

Hallo @buuh,

gerade bei den LCDisplays hatte ich ganz am Anfang erhebliche Probleme.

Um nicht alles hier erörtern zu können, empfehle ich mal den Blick auf meine HP

http://www.kbra01.de/lcd2.htm

Da ist IMHO nun (wirklich) alles zur Initialisierung drin.

Es fehlt IMHO bei Deinem Programm die vollständige Suite:

Vergiß erst mal die int.asm, die vom bekannten "Tutorial" immer wieder
verwendet wird, aber massive Bugs drin hat.

Prinzipielle Fehlerquellen:

Portzuweisungen.

Reihenfolge der Init-Sequenzen

Fehlende bzw. zu kurze Pausen, bzw. Zeitschleifen wurden nicht richtig
assembliert.
Nimm hier keine Platzhalter, sondern formuliere die Schleifen konkret aus.

Du kannst auch 16-Bit-Zeitschleifen nehmen.
Dadurch wird das "Hängenbleiben" verhindert, denn gerade längere Zeitschleifen mögen die AVR MCUnits zumal im 8Bit Register-Modus garnicht.

Beispiel für "meine" LCD-Initialisierungsroutinen und Ausgabeprogramme
findest Du im angehängten ASM-File.

Viel Spaß
Es wird schon klappen.

Übrigens, bitte nicht mit separater 5Volt Versorgung arbeiten, das Backpowering zerstört unter Umständen die LCD-Port-MOS-Fets.
So war es bei meinem ersten Display (auch mit Samsung-Controller) nämlich.
Klemm es getrost an die STK-Power an.
Der Stromverbrauch ohne Hintergrundbeleuchtung dürfte kaum ins Gewicht fallen.

Sollten noch Fragen aufkommen, bin ich gerne behilflich. (Portbits noch umschreiben, so, wie Du es hattest, ist im Prog nicht so !!!)

Gruß von Oskar01

P.S.: Den String in Deinem Programm:
in temp3, LCD_PORT
kapier ich nicht ?!
 

Anhänge

  • LCD-INIT-4Bit.asm
    6 KB · Aufrufe: 27
Hallo @ Oskar

auf deiner Seite war ich sogar schon mal :)

Als Anfänger bin ich halt darauf angewiesen bereits geschrieben Codes zu verwenden und daraus zu lernen in dem ich die Zeilen verstehe und sie dann nach ner weile ändere...

Wie ich gelesen hab gings dir ja ähnlich mit den LCDs und dann weist du auch wie frustriert man ist wenn man tage lang vor dem Ding sitzt und tippt und im endeffeckt kommt doch nix dabei raus...

Ich werde heut morgen mal versuchen die Oskar-Init umzuschreiben und hoffentlich ein erfolgserlebnis finden :(
Sollte das dann klappen werde ich mich an ne eigene ran wagen :eek:
 
Also hab gerade versucht den Code umzuschreiben aber geklappt hat es natürlich nicht wie solls auch anderst sein?!
Naja vielleicht bin ich einfach nur zu müde nach der Nachtschicht...

@Oskar
Du würdest mir einen sehr großen gefallen tun wenn du den Code kurz für mich umschreibst...
oder wäre das zu viel verlangt...?
 
Hallo Buuuh,

ich hatte ja schon mal gefragt...

Die Delays im Programm sind im Moment für fclk=12MHz ausgelegt, wenn der AVR einen höheren Takt erhält, könnten die Delays innerhalb des Initialisierungsbereichs zu kurz sein. Prüfe das doch mal, das ist ne Sache von 30 Sekunden, wenns nicht daran liegt, kann man immer noch am Code basteln.

Dirk
 
Hallo Dirk,

der AVR kann ja theoretisch nur 12 Mhz haben da nur 12 MHz Quarz dran hängt...
bei meinem Lauflicht haben die delayzeiten auch funktioniert...
denkt ihr es würde was bringen das ganze mal im 8 bit modus zu versuchen?
oder lieber gleich zum fenster raus werfen und als gescheitert betrachten? :mad:
 
Hallo buhhh,

sorry hatte folgendes übersehen:
... Hab zum anfangen ein STK 600 Board mit nem ATmega16 und 12Mhz Quarz ...


Was mir so noch einfällt ...

Sind die logischen Zustände von DB0..DB3 vom Display definiert?

Ich vermute, dass sich während der Programmierung des Mikrocontrollers einige logische Zustände der Pins (insbesondere E) zum Display ändern, so dass das Display nicht gleich das macht, was es machen soll. Das Display hat nur einen PowerOnReset, oder?

Dirk
 
was genau meinst du den mit dem poweronreset?
DB0 - DB3 hatte ich am anfang einfach in der Luft hängen, hab sie dann aber doch fest auf masse gelegt...
Ist doch richtig so oder?
 
hab noch ne frage. Wenn mein Init so aussehen soll wie im Anhang was muss ich dann an das LCD schicken? soll ich dann in der ersten zeile nur 0x00 senden und in der zweiten ganz normal?
 

Anhänge

  • datenblattKS0070B.pdf
    29,1 KB · Aufrufe: 15
was genau meinst du den mit dem poweronreset?

Nachdem die Betriebsspannung an das LCD angelegt wird, wird im Displaymodul ein RESET ausgeführt (PowerOnReset), du musst dann einige Zeit warten (30ms) bevor du dem Display etwas sendest, weil das Display Initialisierungen durchführt.

Wenn nun permanent Betriebsspannung am Display anliegt und sich die Zustände der Interfacepins des AVR während der Programmierung ändern, kann es passieren, dass ungewollt Daten/Kommandos an das Display übertragen werden. Es ist dann möglich, dass das Displaymodul Zeichen nicht mehr richtig darstellt, im Extremfall benötigt es einen PowerOnReset und danach eine neue Initialisierung durch deine Software.

DB0 - DB3 hatte ich am anfang einfach in der Luft hängen, hab sie dann aber doch fest auf masse gelegt...
Ist doch richtig so oder?
Da musst du mal im Datenblatt vom Displaymodul oder LCD-Controller nachsehen, bei manchen Display reicht es aus, dass DB0..DB3 einfach offen gelassen werden können.

Dirk
 
Hallo,

hab noch ne frage. Wenn mein Init so aussehen soll wie im Anhang was muss ich dann an das LCD schicken? soll ich dann in der ersten zeile nur 0x00 senden und in der zweiten ganz normal?
du hast ja DB4..7 mit PD0..3 verbunden.
Außerdem hängen bei dir RS an PD4 und E an PD5
E braucht positive Pulse - muß also sonst auf 0 liegen (bit5)

Dann müßtest Du also folgendes laden ... (ich nehme jetzt mal 2 Zeilen an)

--- Function Set ---
1. - 0x02
2. - 0x02
3. - 0x0C (2 Zeilen, 5x7 Dots)
dann die >39us warten
--- Display On/Off Control ---
4. - 0x00
5. - 0x0C (Display on, Cursor off, Blink off)
dann wieder >39us warten
--- Clear Display ---
6. - 0x00
7. - 0x01
warten >1,53ms
--- Entry Mode Set ---
8. - 0x00
9. - 0x06 (Inc , No Shift)
--- Ende ---

So sollte es laufen (theoretisch ;) )

Dran denken wenn du dein Byte zum senden in das Port-Register lädst ...
Du hast neben den Bits 0..3 für die Daten auf Bit 4 dein RegisterSelect und
auf Bit 5 noch das Enable. Wenn Du Daten überträgst mußt Du also beim
oberen Nibble eine 0x1 reinschreiben. Also Bit 4 setzen.

Also bei den Daten 0x4C müßtest du folgendes übertragen ...

0x14 -> RS = 1 , Datenbits 7..4 (4)
0x1C -> RS = 1 , Datenbits 3..0 (C)

verstanden ?

Gruß
Dino
 
Bugfixing completed

Hallo,
in das oben angehängte ASM-File hatte sich ein übler Fehler eingeschlichen.
Die Doppelregister können maximal mit FFFF also 65535 beschrieben werden.
(Hier bin ich also selbst auf den Tutorial-Beitrag 'reingefallen.)
Auch r24 und r25 können u. U. zu 16-Bit-Registern zusammengefaßt werden,
bei den noch niedrigeren laufen die zugehörigen 16-Bit-Befehle nicht bzw.
nicht richtig, jedenfalls klappte es im Testlauf hier dann nicht mehr.
Man kann natürlich auch die für die Pointer prädestinierten Registerpaare X,Y, und Z nehmen, es sei denn, sie wären wie im untigen Beispiel bereits z. T. "predefined", was der Assembler dann auch bemerkt.

Das Programm zeigt nun eine vollständige Initialisierung eines 16x2 LCDs.
Es erscheint ein Textaufbau Buchstabe für Buchstabe von oben links mit Zeilenumbruch auf zweite Zeile.
Dann wird das Display wieder gelöscht, Entry-Mode-Set geändert, so daß
der Text nun von rechts kommend dergestalt ins Display geschrieben wird,
daß der blinkende Cursor am rechten Rand stehen bleibt, die Buchstaben wandern.
Man sieht dann auch gleich die Problematik der Zeichenpositionierung, die
für das "Rückwärtsschreiben" dann auf der zweiten Zeile nur einen Teil des Textbestandteils zeigt.
Die Zeichenpositionierung für Zeile 2 wurde wie beim "Vorwärtsgang" nämlich beibehalten. Nur aus diesem Grunde wurden die Textbestandteile gesplittet in zwei Pointerarrays, wobei vor dem zweiten noch die Angabe für den Zeilenumbruch kommt.
Bekanntermaßen werden für 16x2 und auch andere Displays Controller verwendet, die nach wie vor für 40 Zeichen pro Zeile angedacht sind, somit
sonst den Rest in den nicht darstellbaren Adressbereich schreiben würden.

Das Proggi wurde nochmals getestet und müßte eigentlich so auch bei anderen AVR MCUs funktionieren. Dafür müssen noch include-files und evtl.
Stackpointer aktualisiert werden.

Die Portbits der Daten- und Steuersignale sollten auch richtig gesetzt werden.
Da ich Hardware schon fixiert hatte, hätte ich es sonst nicht hier testen können, wären die Dinge nicht so wie bei mir benutzt, bestehen geblieben.

Falls gewünscht, ändere ich es nochmal ab auf Eure Bedürfnisse, aber, glaube ich, das ist wohl nicht nötig.

Viel Spaß,
Gruß von Oskar01

P.S. Hallo @buu..., also ich schreib's gleich mal um.
Prämissen:
ATmega16 und 12Mhz ,
PD0 - PD3 an DB4 - DB7
und
RS an PD4 u E an PD5
so wars doch?

Nimm mal das File vom Folgethread.
Ich lösche jetzt das hier angehängte Proggi mal. Es trägt sonst zur möglichen Verwirrung bei, da die Portzuweisungen etc. noch nicht Deinen Bedürfnissen angepaßt wurden. Obwohl das eigentlich nicht die "feine Englische Art" ist, Treads hernach noch zu korrigieren.
 
Code auf ATMega16 angepaßt

Hallo @buhh....,
bitteschöööön:

Also, Assembler sagt "No errors, no warnings",
Simulationstest sieht auch gut aus.
Hab leider keine passende MCU hier, also leider kein Praxistest möglich....

Probiers mal,
wenn es noch Probs gibt, melde Dich bitte noch mal.


Gruß von Oskar 01
-------------------------------------------

Noch ein bißchen zum Hintergrund und Deinem speziellen Ansteuerproblem, lieber @ Buhhh...:


Du nimmst ja "nur" die "untere" Porthälfte des MCU-Registers Port "Dora",
also am Anfang der LCD-Init-Routine wird Anpassung einfach durch Umdrehen der Hex-Werte möglich. Also statt ganz am Anfang dreimal $30 dann $03.

Ob nun eine Null ("low") im Programm drin ist, oder diese Null dadurch dem Controller vorgespiegelt wird, indem die entsprechenden LCD-"Eingänge" nun auf Masse (über Widerstände) fest verdrahtet wurden, spielt keine Rolle. Null ist Null. Das geht so lang gut,
wie halt Variablen lediglich 4 Bits enthalten.

Das ist in der Tat nur beim ersten Init-String und beim Vorbereitungsstring für den Vierbit-Modus so.

(Fehlt in der Beschreibung im einkopierten Datenblattauszug völlig, ich weiß. Gehört aber rein. Da läßt sich nichts dran rütteln, auch, wenn darüber ein Glaubensstreit entfacht wird unter Experten, ich bleibe hier beinhart. Das Init-Schema im Datenblatt legt gleich mit Hex28 los. Das ist komplett falsch. Ich muß doch erst einmal dem Controller sagen, daß jetzt der Übergabemodus geändert werden muß, erst dann kann ich ihm einen Befehl geben, der in dem Modus sendet, in den er jetzt gerade vor Mikrosekunden hereingesprungen sein sollte, gelle? Erst drücke ich die Bremse am Auto, dann Gaspedal. So fährt es nie los, umgekehrt muß es sein.)

Bei Deiner Programmvariante müßte nun berücksichtigt werden, daß Du bereits hardwaremäßig
den Port "Dora" "geswappt" hast, also, wenn ich Dich richtig verstehe, hast Du D0 bis D3 mit
D4 bis D7 des LCD-Busses fest verdrahtet, dabei D0 bis D3 des LCD-Busses fest auf Masse
gelegt. Aus der Sicht des Displays ist das völlig korrekt.


Mit dem Swappen bei Ausgaberoutinen für ASCII-Charaktercode-Übernahme (Label "datenuebernahme") beziehungsweise Steuerbefehlsübernahme (Label "kommando") wird es aus oben Gesagtem heraus schon ein wenig trickreicher. Hier brauche ich ja 8 Bits, da die Argumente ( und der ASCII-CHarakter-Code) aus 8 Bits bestehen.

Die Prämisse:
Der Controller will im Vierbitmodus immer das "Highnibble" (- aus der Sicht des MCU-Ports gesehen-) zuerst serviert bekommen.
Nach jeder Ausgabe am Port der MCU erfolgt Einschreiben in Display-Puffer mit der fallenden Flanke des Enableimpulses.
Es ist kein "statisches" Bit - vergleichbar dem RegisterSelect-, sondern auf die 50 Nanosekunden der fallenden Flanke kommt es an. ( - Schaltungstechnisch wird das im Displaycontroller lediglich durch eine klitzekleine Gatterverzögerung erreicht. - ).
Da ich in zwei Gruppen Argumente übergebe, brauche ich auch zwei Enableimpulse. Für jedes Nibble ein separates. Das macht aber schon das Label "kommando" ( -ebenso "datenuebernahme" -) selbständig, indem es wiederum das Label "enable" aufruft.

Ist das zweite Nibble, das "untere", nennen wir es jetzt mal so, ebenfalls mit Enableimpuls übernommen worden, setzt der Controller das wieder zu einem Achtbit-Argument intern zusammen. Nur die Reihenfolge muß stimmen, sonst kommt Ergebnis raus, das nicht dem gewünschten entspricht.
Der folgende Steuerbefehlssatz ist völlig identisch in beiden "Übergabearten" Achtbit- wie Vierbit-Modus. Nur die Art und Weise, wie die Steuerbefehle (Daten) gesendet werden, ist abweichend.
Das Datenblatt erklärt garnichts und trägt zur kompletten Verwirrung bei, zumal da auch RS und RW in derselben Zeile ohne besondere Hervorhebung links neben die Portinhalte geschrieben wurden.
Was uns eigentlich nur interessiert, ist, wo die Bits an der MCU am auserwählten Port anliegen und wie sie am klügsten auf den LCD-Port gelegt werden, beziehungsweise, was der LCD-Controller von uns erwartet. Die Autoren des LCD-Init-Schemas im Datenblatt gehen von Voraussetzungen aus, die sich hier nicht anwenden lassen und völlig praxisfremd sind.

"Datenuebernahme"- und "Kommando"-Label sind jetzt im angehängten File LCD_AT16.asm so "swap"-mäßig angepaßt, wie es sein müßte, denke ich mal.

Die Ver"und"ungen und Ver"oder"ungen sind deswegen nötig, weil auf denselben Ausgabeport
nun auch noch zeitlich unabhängig auf bislang für die reine Datenübertragung ungenutzen Bits die Steuersignale Enable und Registerselect in Übereinstimmung mit dem Timingdiagramm, das der Controller voraussetzt, aktiv mit der alternativen Methode des direkten Portbit-Setzens- bzw. -Löschens per "sbi"- bzw. "cbi-"Anweisungen erfolgen müssen. Sonst klappt es nicht.

Also:
Zuerst RS, dann Daten/Steuersignale, die so lange erhalten bleiben, bis der Port wieder überschrieben wird, dann Enable auf high und wieder auf low, dann RS wieder.
Andersherum: Würde ich nur per Ausgabebefehl "out" arbeiten, käme ich mit den Steuesignalen timingmäßig ins Gehege. Auch würde ich unter Umständen dann diese Steuersignale "mitswappen". Das wäre völlig abwegig. Hab's ausprobiert und gibt nur
Probleme.

Noch etwas, habe das m16-include-File genommen, evtl. nimmst Du noch Dein aktuelles Inc.File.

Frage am Rande, gibt es einen speziellen Grund, daß Du D0 bis D3 ans Display anschlossest und nicht gleich D4 bis D7, im Endeffekt ist der Port ja sowieso durch RS und Ena schon "besetzt". Hmmm? Umlötung nicht angesagt? -- Aber lassen wir das, jetzt müßte das Problem auf der Softwareseite doch einigermaßen faßbar sein.--
 

Anhänge

  • LCD_ATM16.asm
    9,7 KB · Aufrufe: 16
So nun nach dem Wochende habe ich den entschluss gefasst, dass ganze Thema erst mal ruhen zu lassen... (mir fehlt für sowas einfach die geduld...)

Hab schon die Tage davor ein zweites Display bestellt das ich später eigentlich auch benutzen wollte und auch werde, dazu aber eine Platine ätzen werde auf der ich nen 12 pol. Pin Connector hab zum anstecken ans STK600.
Auch werd ich dann die Versorgungsspannung vom STK600 holen und nicht mehr extern.
Das ganze bietet sich an da ich gerade eh ne kleine eigene Ätzanlage bastle und dann so auch gleich testen kann...

Sollte bis Mittwoch erledigt sein, dann kann ich über die "freien Tage" wieder programmieren.

Ein fettes Dankeschön :flowers: an Oskar und natürlich die anderen auch für die hilfe!

Zu deiner frage @Oskar wegen PD0 - 3. Ich bin an das ganze Thema mit Null ahnung rangegangen, hab vorher noch nie ne mikrocomputer gesehn...
Ich hab mich auf Anleitungen verlassen die man Online findet und dachte eigentlich das es ohne großen Aufwand einfach funktioniert.
Mittlerweil ist mir die funktion eines LCDs schon ziemlich klar...
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)