;---------------------------------------------------------------------------- ; Funktionen zum Ansteuern eines parallelen LCD-Displays ; Variante für das UniKiel-Board ; geht allgemein für Display Typ 162, 204A von Displaytech ; benutzt: Acc, BReg ; Achtung: ZAnz, LAnz im Hauptprogramm vereinbaren! ;---------------------------------------------------------------------------- ; LCD_init: muss zuerst aufgerufen werden ; LCD_clear: lösche Bildschirm ; LCD_printbd: Ausgabe eines Bytes als Zahl (ACC, dezimal) ; LCD_printc: Ausgabe eines Bytes als String (ACC) ; LCD_prints: Ausgabe eines Strings (DPTR, Nullterminiert) ; LCD_line: auf nächste Zeile gehen ; LCD_com: Befehl aus Acc an LCD senden ; LCD_read_data: Daten aus LCD auslesen (DDRAM/CGRAM) ;---------------------------------------------------------------------------- ; benötigt werden: ; - Time.inc ; - Zeichen/Zeile ZAnz ; - Zeilenzahl LAnz ; - Pin Enable EN ; - Pin R/W RW ; - Pin RS RS ; - ein halber Port Port benutzt wird Px.0 bis Px.3 ;---------------------------------------------------------------------------- DSEG ; RAM Daten Line: DS 1 AZahl: DS 1 ;********************** CSEG ; Routinen LCD_clear: push Acc mov a,#01h ; LCD Clear acall LCD_com mov AZahl,#ZAnz+1 ; setze Zeilenzähler mov Line,#0 pop Acc ret ;********************************************************************* LCD_init: ; LCD initialisieren ; einige ms warten, bis sich der Spannungspegel stabilisiert hat push Acc mov a,#150 acall _delay clr RS clr RW clr EN mov a,#30h ; 8Bit-Mode acall _send8 mov a,#30h ; 8Bit-Mode acall _send8 mov a,#30h ; 8Bit-Mode acall _send8 mov a,#20h ; 4Bit-Mode acall _send8 mov a,#10 acall _delay mov a,#28h ; 4Bit-Mode, 2 Zeilen, 5x8 Dots acall LCD_com mov a,#0Ch ; LCD on, Cursor on, Blink off acall LCD_com mov a,#06h ; Shift aus, Cursor rechts acall LCD_com pop Acc acall LCD_clear ret ;************************************************************************** ; sendet im 8 Bit Modus _send8: swap a anl a,#0Fh setb EN anl Port,#0F0h orl Port,a nop clr EN mov a,#10 acall _delay ret ;*************************************************************************** ; Abfrage Busy Flag LCD_busy: push Acc mov Port,#0Fh ; Port LNibbel auf Lesen stellen clr RS ; auf Lesen setb RW _B01: nop nop setb EN nop mov a,Port ; 4 Bit Daten lesen clr EN swap a nop setb EN nop clr EN ; 2te Abfrage ohne Port jb Acc.7,_B01 ; Busy gesetzt warten pop Acc mov Port,#00h ; Port auf Ausgang ret ;************************************************************************* ; Ausgabe eines Zeichens an LCD ; Übergabe Zeichen im Akku LCD_printc: djnz AZahl,LCD_pr01 ; Zeilenende erreicht? acall LCD_line ; ja, neue Zeile LCD_pr01: acall LCD_send_d ; Zeichen ausgeben ret ;************************************************************************* ; Ausgabe eines Bytes als Zahl ; Byte im Akku übergeben LCD_printbd: push B ; BReg wird benötigt mov B,#100 div AB ; teile die Zahl durch 100 add a,#30h ; addiere Hex 30 wegen ASCII acall LCD_printc ; gebe das entsprechende Zeichen aus mov a,B ; hole den Rest mov B,#10 div AB ; teile durch 10 add a,#30h ; wandle in ASCII um acall LCD_printc mov a,B ; hole Rest (Einerstelle) add a,#30h ; wandle in ASCII acall LCD_printc pop B ; BReg original ret ;************************************************************************ ; Ausgabe eines mit 0 terminierten Strings aus DPTR ; Textadresse in DPTR LCD_prints: push Acc ; rette Akku _anf: clr a movc a,@A+DPTR ; hole Inhalt von DPTR+Akku nach Akku inc DPTR jz _end ; =0? ja, dann fertig djnz AZahl,_weit ; Zeilenende erreicht? acall LCD_line ; ja, neue Zeile _weit: acall LCD_send_d ; gebe Byte aus sjmp _anf _end: ; fertig pop Acc ; Akku original ret ;*********************************************************************** ; auf Zeilenlänge prüfen und ggf weiterschalten ; hier fehlt noch die Zeilenbeschränkung gemäß LAnz LCD_line: push Acc ; rette Akku push DPH ; rette Textzähler push DPL mov DPTR,#DDAddr ; hole Adresse Zeilencode inc Line ; nächste Zeile mov a,Line ; in Acc movc a,@a+DPTR ; Zeilencode nach Akku orl a,#80h ; setze MSB für DDRAM acall LCD_com ; Befehl ausgeben mov AZahl,#ZAnz ; Zeilenlänge neu pop DPL ; ja, Textzähler zurück pop DPH pop Acc ; Akku zurück ret DDAddr: DB 00H,40H,14H,54H ;*********************************************************************** ; sendet Befehle aus ACC an Port, zuerst High, dann Low-Nibble LCD_com: acall LCD_busy clr RS ; 1=Daten, 0=Befehl clr RW ; R/W: Read=1 - Write=0 ajmp LCD_send ;********************************************************************** ; sendet Daten aus ACC an Port, zuerst High, dann Low-Nibble LCD_send_d: acall LCD_busy clr RW ; R/W: Read=1 - Write=0 setb RS ; 1=Daten, 0=Befehl LCD_send: push Acc ; speichere Byte swap a ; vertausche H- mit LNibbel anl a,#0Fh ; HNibbel Akku löschen anl Port,#0F0h ; LNibbel Port löschen orl Port,a ; Setze LNibbel Akk nach LNibbel Port setb EN nop clr EN pop Acc ; hole das Byte zurück anl a,#0Fh ; HNibbel Akku löschen anl Port,#0F0h ; LNibbel Port löschen orl Port,a ; LNibbel Akku in LNibbel Port setb EN nop clr EN ret ;*********************************************************************** ; Daten aus DDRAM oder CGRAM auslesen ; Ergebnis steht in Acc LCD_read_data: acall LCD_busy push B ; BReg retten mov Port,#0Fh ; Port LNibbel auf Lesen stellen setb RS ; auf Lesen setb RW R_01: nop nop setb EN nop mov a,Port ; 4 Bit Daten lesen clr EN anl a,#0Fh swap a nop nop nop setb EN nop mov B,Port ; 4 Bit Daten lesen clr EN ; 2te Abfrage ohne Port anl B,#0Fh orl a,B ; Acc und BReg zusammenfügen mov Port,#00h ; Port auf Ausgang pop B ; Original BReg zurück ret ;************************************************************************ ; Warteschleife für 8 MHz -> 1MC = 1,5µsec 1msec = 667 MC _delay: ; Acc x 1 mSec push Acc ; 2MC mov a,#220 ; 2MC _wart1: ; 220 x 3 MC = 660 MC nop ; 1MC djnz ACC,_wart1 ; 2MC pop Acc ; 2MC djnz 0E0h,_delay ; 2MC ret ; 2MC ;************************************************************************