;
; *******************************************************
; * Include-Routinen zur LCD-Ansteuerung, stellt die *
; * Basisroutinen fuer die Initiierung einer LCD und die*
; * Textausgabe zur Verfuegung, ausgelegt fuer ein- und *
; * mehrzeilige LCDs, 8-bit-interface, HD44780-kompati- *
; * ble Displays *
; * (C)2006 by g.schmidt, info!at!avr-asm-tutorial.net *
; *******************************************************
;
;
; Charakteristiken der Hardware:
;
.EQU pLcdDataOut = PORTD ; Daten-Port mit dem LCD verbunden ist
.EQU pLcdDataIn = PIND ; dto., der Eingabe-Port
.EQU pLcdDataDir = DDRD ; dto., Port-Richtung
.EQU pLcdEOut = PORTB ; Kontroll-Port Bit E der LCD
.EQU pLcdEDir = DDRB ; dto., Richtungs-Bit
.EQU pLcdRsOut = PORTB ; dto., Bit LCD-RS der LCD
.EQU pLcdRsDir = DDRB ; dto., Richtungs-Bit
.EQU bLcdEOut = 0 ; Port-Bit E der LCD
.EQU bLcdRSOut = 4 ; Port-Bit RS der LCD
;
; Weitere Bedingungen zum Assemblieren:
;
; Typ Name Erlaeuterung
; -----------------------------------------------------------
; Konstante Clock Prozessorfrequenz in Hz, Bereich 1..16 MHz
; cLcdLw Anzahl Zeichen pro Zeile der LCD
; cLcdLn Anzahl Zeilen der LCD (1 oder 2)
; Register rmp Multi-Purpose Register (R16..R31)
; -----------------------------------------------------------
;
; Stellt folgende Routinen zur Verfuegung:
;
; Name Parameter Erfuellt folgende Aufgaben
; ---------------------------------------------------------
; LcdInit Z:Text1 im Flash Initiiert die LCD and zeigt
; Speicher (null- den Text1 an auf den Z zeigt,
; terminiert), wartet fuer 1.5 Sekunden und
; Zeilen durch
; getrennt
; X:Text2 im Flash zeigt Text2 an, auf den X
; Verwendet R25:R24 zeigt
; LcdFlash Z: Text im Flash Zeigt den Text im Flash-
; speicher an, auf den Z zeigt
; LcdHome -- Setzt die Anzeigenposition
; den Beginn von Zeile 1
; LcdChar R0 = Zeichen Schreibt das Zeichen in R0
; an die aktuelle LCD-Position
; LcdLine1 Z:Text im SRAM Zeigt den Text im SRAM auf
; Zeile 1 der LCD an
; LcdLine2 Z:Text im SRAM Zeigt den Text im SRAM auf
; Zeile 2 der LCD an
; -----------------------------------------------------
;
; -----------------------------------------------
; L C D I N I T I I E R U N G R O U T I N E
; -----------------------------------------------
;
LcdInit:
cbi pLcdEOut,bLcdEOut ; loesche LCD Enable Bit
sbi pLcdEDir,bLcdEOut ; E-Bit ist Ausgang
sbi pLcdRsDir,bLcdRSOut ; dto., RS-Bit
rcall Delay360ms ; warte auf die LCD-interne Initiierung
ldi rmp,0xFF ; setze LCD-Datenport auf Ausgang
out pLcdDataDir,rmp
rcall Delay15ms ; warte 15 ms fuer interne Initiierung
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
.IF cLcdLn == 1
ldi rmp,0x30 ; setze 8-Bit-Interface, einzeilige LCD
.ELSE
ldi rmp,0x38 ; setze 8-Bit-Interface, zweizeilige LCD
.ENDIF
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
ldi rmp,0x08 ; Display abschalten
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay40us ; warte 40 us
ldi rmp,0x01 ; Display loeschen
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall Delay1m64s ; warte 1.64 ms
ldi rmp,0x06 ; Increment ein, Shift aus
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
ldi rmp,0x0C ; activiere Display, kein Cursor, kein Blinken
rcall LcdStrobeC ; schreibe Kontrollwort an LCD
rcall LcdHome ; setze Cursorposition auf Anfang Zeile 1
rcall LcdFlash ; Schreibe Text im Flash ab Z auf Display
rjmp Delay2s5 ; warte fuer 2.5 Sekunden
;
; -------------------------------------------------
; L C D S C H R E I B - S U B R O U T I N E N
; -------------------------------------------------
;
; Schreibe Text ab Position Z im Flash auf Display
;
LcdFlash:
lpm ; lese naechstes Zeichen aus dem Flashspeicher
tst R0 ; Ende des Textes erreicht?
breq LcdFlash2
.IF cLcdLn>1
ldi rmp,0x0D ; Wagenruecklauf-Zeichen?
cp rmp,R0
brne LcdFlash1 ; zeige Zeichen an
ldi rmp,0xC0 ; Adresse von Zeile 2
rcall LcdStrobeC ; an Kontrollport der LCD
rcall Delay40us ; 40 us Verzoegerung
adiw ZL,1 ; naechstes Zeichen
rjmp LcdFlash ; und weiter
LcdFlash1:
.ENDIF
out pLcdDataOut,R0 ; Zeichen in R0 an Datenport
sbi pLcdRsOut,bLcdRSOut ; setze RS-Bit
rcall LcdStrobeE ; E-Bit pulsen
cbi pLcdRsOut,bLcdRSOut ; loesche RS-Bit
rcall Delay40us ; 40 us Verzoegerung
adiw ZL,1
rjmp LcdFlash ; naechtes Zeichen
LcdFlash2:
ret
;
; Setzt die LCD-Ausgabeposition auf den Anfang von Zeile 1
;
LcdHome:
ldi rmp,0x02 ; setze Kontrollwort fuer Home
rcall LcdStrobeC ; schreibe Kontrollwort
rjmp Delay1m64s ; warte 1,64 ms
;
; gibt das Zeichen in rmp als Kontrollwort aus und pulst das E-Bit
;
LcdStrobeC:
out pLcdDataOut,rmp ; schreibe Kontrollwort auf Datenport
cbi pLcdRsOut,bLcdRSOut ; loesche RS-Bit
;
; Pulst E-Bit mit korrekter Dauer
;
LcdStrobeE:
sbi pLcdEOut,bLcdEOut ; setze E-Bit Eins
nop ; warte mindestens 1 Zyklus
.IF Clock>2 ; mehr als 2 MHz Takt
nop ; zwei NOP
.ENDIF
.IF Clock>4 ; mehr als 4 MHz Takt
nop ; drei NOP
.ENDIF
.IF Clock>6 ; mehr als 6 MHz Takt
nop ; vier NOP
.ENDIF
.IF Clock>8 ; mehr als 8 MHz Takt
nop ; fuenf NOP
.ENDIF
.IF Clock>10 ; mehr als 10 MHz Takt
nop ; sechs NOP
.ENDIF
.IF Clock>12 ; mehr als 12 MHz Takt
nop ; sieben NOP
.ENDIF
.IF Clock>14 ; mehr als 14 MHz Takt
nop ; acht NOP
.ENDIF
cbi pLcdEOut,bLcdEOut ; loesche E-Bit
rjmp Delay40us ; Verzoegerung 40 us
;
; Zeige Zeichen in R0 an
;
LcdChar:
out pLcdDataOut,R0 ; Ausgabe des Zeichens in R0
sbi pLcdRsOut,bLcdRSOut ; setze RS-Bit
rjmp LcdStrobeE ; pulse E-Bit
;
; Zeigt den Text ab Z im SRAM auf Zeile 1 der LCD an
;
LcdLine1:
ldi rmp,0x80 ; setze Cursor auf Zeile 1
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine1a:
ld R0,Z+ ; lese naechstes Zeichen aus SRAM
rcall LcdChar
dec rmp
brne LcdLine1a
ret
;
; Zeigt den Text ab Z im SRAM auf Zeile 2 der LCD an
;
LcdLine2:
ldi rmp,0xC0 ; setze Cursor auf Zeile 2
rcall LcdStrobeC
ldi rmp,cLcdLw
LcdLine2a:
ld R0,Z+ ; lese naechstes Zeichen aus SRAM
rcall LcdChar
dec rmp
brne LcdLine2a
ret
;
; -------------------------------------------------------------
; V E R Z O E G E R U N G S R O U T I N E N F U E R L C D
; -------------------------------------------------------------
;
.SET clockus = clock/1000000
.IF clockus == 0 ; Clock kleiner als 1 MHz
.SET clockus = 1
.ENDIF
;
; Verzoegerung fuer 2.5 Sekunden
;
Delay2s5:
push rmp
ldi rmp,2500/15+1 ; Anzahl 15ms-Verzoegerungen
Delay2s5a:
rcall Delay15ms
dec rmp
brne Delay2s5a
pop rmp
ret
;
; Verzoegerung fuer 360 Millisekunden
;
Delay360ms:
push rmp
ldi rmp,360/15+1 ; Anzahl der 15ms-Verzoegerungen
Delay360ms1:
rcall Delay15ms
dec rmp
brne Delay360ms1
pop rmp
ret
;
; Verzoegerung fuer 15 Millisekunden
;
Delay15ms:
push ZH ; sichere Z
push ZL
ldi ZH,HIGH((15000*clockus-16)/4)
ldi ZL,LOW((15000*clockus-16)/4)
Delay15ms1:
sbiw ZL,1
brne Delay15ms1
pop ZL
pop ZH
ret
;
; Verzoegerung fuer 1.64 Millisekunden
;
Delay1m64s:
push ZH ; sichere Z
push ZL
ldi ZH,HIGH((1640*clockus-16)/4)
ldi ZL,LOW((1640*clockus-16)/4)
Delay1m64s1:
sbiw ZL,1
brne Delay1m64s1
pop ZL
pop ZH
ret
;
; Verzoegerung 40 Mikrosekunden
;
Delay40us:
push rmp
ldi rmp,(40*clockus-11)/3
Delay40us1:
dec rmp
brne Delay40us1
pop rmp
ret
;
; Ende der LCD-Routinen
;