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 ...
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
)
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.
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
Gruß
Dino