;LCD Displayroutinen fuer Batronix Testboard Adressierung ;getestet mit verschiedenen Displays mit dem Controller ;Hitachi HD44780 und kompatibel ; ;Wiederverwendung nur für den privaten, nichtkommerziellen Gebrauch ;Quelle: http://www.mikrocontroller-projekte.de ;klaus@mikrocontroller-projekte.de ;Klaus Leidinger, 2001 ; ;Die Library erwartet die definition der Variablen ;Adressen des LCD Ports diese Belegung ist fest bei der 4 Bit Ansteuerung !! ;d.H. Die Bits 0-7 des Ports sind entsprechend Belegt, der Port selbst kann ;natürlich jeder beliebige Port sein. ;LCD_daten equ P1 ;LCD_Busy bit P1_3 ;LCD_RS bit P1_7 ;LCD_RW bit P1_6 ;LCD_E bit P1_5 ;LCD_Light bit P1_4 ;LCDlines equ 2 ;für 2 Zeilige Displays, 1 für einzeilige ;DISPtype equ 40 ;Anzahl Character/Zeile des Displays (16,24 oder 40) ;Folgende Routinen für 4 Bit Ansteuerung sind implementiert: ; LCDini Initialisierung des Displays im 4 Bit Mode ; LCDcls Clear Display, Cursor auf Home ; LCDhome Cursor auf Home, ohne Clear Display ; LCDrdy fuer abfrage des Displayzustandes im 4 Bit Mode ; LCDcom Commando mit RS0 = 0 an LCD ausgeben im 4 Bit Mode ; LCDchr Accu auf LCD Position schreiben im 4 Bit Mode ; LCDtxt text in DPTR auf LCD Position schreiben, Textende mit 0x00 ; LCDtxtL text in DPTR auf LCD Position als Lauftext schreiben ; LCDl1 umschalten auf Zeile 1 (Pos. auf Zeilenanfang) ; LCDl2 umschalten auf Zeile 2 (Pos. auf Zeilenanfang) ; LCDcshiftr Curser um die anzahl von R1 Positionen nach rechts schieben ; LCDcshiftl Curser um die anzahl von R1 Positionen nach links schieben ; LCDxy Cursor auf die Pos. X (=R1), und Y(=R2) setzen, X=1-40, Y=1|2 ; OHNE Loeschen des Displays ; LCDcl1 Clear Zeile 1 ; LCDcl2 Clear Zeile 2 ; LCDwait Warteschleife zum Display lesen (ca 1Sec.) ; LCDLwait Warteschleife für "Lauftexteffekt" ; LCDitoa Zeigt ACC in ASCII HEX auf aktueller LCD Position (8 Bit) ; LCDitoaH Zeigt High Nibble des ACC auf aktueller LCD Position (1 Stelle) ; LCDitoaL Zeigt Low Nibble des ACC auf aktueller LCD Position ; LCDLight_on Schaltet Hintergrundbeleuchtung ein (wo vorhanden) ; LCDLight_off Schaltet Hintergrundbeleuchtung aus (wo vorhanden) ; LCDini Default Initialisierung des Displays im 4 Bit Mode ; Siehe Beschreibung der einzelnen Bits LCDini if LCDlines = 2 MOV A,#00101000B ; DL=0 N=1 F=0 : 4Bit , zwei Zeilen endif if LCDlines = 1 MOV A,#00100000B ; DL=0 N=0 F=0 : 4Bit , eine Zeile endif ACALL LCDcom ; Als Kommando ACALL wait ACALL LCDrdy ; Beendigung des letzten Kommandos abwarten MOV A,#00001100B ; D=1 C=0 B=0 , Display an , Cursor u. Blinken aus ACALL LCDcom MOV A,#00000110B ; I/D=1 S=0 : Increment ohne Display shift ACALL LCDcom ACALL LCDcls ret LCDrdy ; Warte bis LCD fertig ; Lese Zustand von LCD clr LCD_RS ;RS=low setb LCD_RW ;RW=high setb LCD_E JB LCD_Busy,LCDrdy_1 ; Bit 7 is BUSY-Flag clr LCD_E nop setb LCD_E ;lese 2. Hälfte Adressen nop clr LCD_E ret LCDrdy_1 clr LCD_E nop setb LCD_E ;lese 2. Hälfte Adressen nop clr LCD_E ajmp LCDrdy RET ; LCDcom ; Kommando im 4 Bit Modus an LCD ausgeben push ACC ;Daten zwischenspeichern swap A ;High und Low Nibble tauschen, da zuerst High übertragen anl A,#0FH ;ausblenden High Nibble für Befehlecode jb LCD_Light,LCDcom_1 ;anderer Befehl falls Licht an ist orl A,#00100000B ;RS=0, RW=0, E=1, Licht=0 ajmp LCDcom_2 ;weiter mit Befehlsausgabe LCDcom_1 orl A,#00110000B ;RS=0, RW=0, E=1, Licht=1 LCDcom_2 mov LCD_daten,A ;ausgabe Befehl und Daten DB7-DB4 nop ;kurze Wartezeit nop nop clr LCD_E ;fallende Flanke E, 1, Datenhälfte geschrieben nop ;kurze Wartezeit nop nop setb LCD_E ;Pegel für 2. Hälfte Bits pop ACC ;Rückholen ursprünglicher Wert anl A,#0FH ;ausblenden High Nibble für Befehlecode jb LCD_Light,LCDcom_3 ;andere Befehl falls Licht an ist orl A,#00100000B ;RS=0, RW=0, E=1, Licht=0 ajmp LCDcom_4 ;weiter mit Befehlsausgabe LCDcom_3 orl A,#00110000B ;RS=0, RW=0, E=1, Licht=1 LCDcom_4 mov LCD_daten,A ;ausgabe Befehl und Daten DB7-DB4 nop ;kurze Wartezeit nop nop clr LCD_E ;fallende Flanke E, 1, Datenhälfte geschrieben SJMP wt1 ; Warten LCDchr ; Character im 4 Bit Modus an LCD ausgeben push ACC ;Daten zwischenspeichern swap A ;High und Low Nibble tauschen, da zuerst High übertragen anl A,#0FH ;ausblenden High Nibble für Befehlecode jb LCD_Light,LCDchr_1 ;andere Befehl falls Licht an ist orl A,#10100000B ;RS=1, RW=0, E=1, Licht=0 ajmp LCDchr_2 ;weiter mit Befehlsausgabe LCDchr_1 orl A,#10110000B ;RS=1, RW=0, E=1, Licht=1 LCDchr_2 mov LCD_daten,A ;ausgabe Befehl und Daten DB7-DB4 clr LCD_E ;fallende Flanke E, 1, Datenhälfte geschrieben nop ;kurze Wartezeit setb LCD_E ;Pegel für 2. Hälfte Bits pop ACC ;Rückholen ursprünglicher Wert anl A,#0FH ;ausblenden High Nibble für Befehlecode jb LCD_Light,LCDchr_3 ;andere Befehl falls Licht an ist orl A,#10100000B ;RS=1, RW=0, E=1, Licht=0 ajmp LCDchr_4 ;weiter mit Befehlsausgabe LCDchr_3 orl A,#10110000B ;RS=1, RW=0, E=1, Licht=1 LCDchr_4 mov LCD_daten,A ;ausgabe Befehl und Daten DB7-DB4 clr LCD_E ;fallende Flanke E, 1, Datenhälfte geschrieben ; Zeichen in A via LCD ausgeben wt1 MOV R0,#250 ; 100 Mikrosekunden wt2 DJNZ R0,wt2 ; warten MOV R0,#250 ; Doppelt weil Quarzfrequenz 24 Mhz wt3 DJNZ R0,wt3 ; warten RET ;textausgabe auf LCD Display LCDtxt mov R1,#DISPtype ;Counter fuer Zeilenwechsel lcdtxt1 mov A,#0 ;loesche Accu movc A,@A+DPTR jz end_lcdtxt ;bei NULL Byte ende cjne A,#10,lcdtxt2 ;bei CR Zeilenvorschub inc DPTR sjmp lcdlf lcdtxt2 lcall LCDchr ;Zeichen ausgeben inc DPTR ;Adresszaehler hochzaehlen djnz R1,lcdtxt1 lcdlf acall LCDl2 ;Zeilenvorschub sjmp lcdtxt1 end_lcdtxt ret LCDtxtL mov R1,#DISPtype ;Counter fuer Zeilenwechsel lcdtxtL1 mov A,#0 ;loesche Accu movc A,@A+DPTR jz end_lcdtxtL ;bei NULL Byte ende cjne A,#10,lcdtxtL2 ;bei CR Zeilenvorschub inc DPTR sjmp lcdLlf lcdtxtL2 lcall LCDchr ;Zeichen ausgeben inc DPTR ;Adresszaehler hochzaehlen lcall LCDLwait djnz R1,lcdtxtL1 lcdLlf acall LCDl2 ;Zeilenvorschub sjmp lcdtxtL1 end_lcdtxtL ret LCDl1 mov A,#10000000B ;LCD Commando HOME acall LCDcom ret LCDl2 mov A,#11000000B ;LCD Commando Zeile 2 acall LCDcom ret LCDcls MOV A,#00000001B ;Reset Display ACALL LCDcom wait MOV R0,#255 ; Warte ein Weilchen wait1 MOV R1,#255 wait2 ; 255*4 Mikrosec NOP NOP DJNZ R1,wait2 DJNZ R0,wait1 ; * 255 RET ; ca 65500*4 Mikrosekunden LCDhome acall LCDrdy mov A,#00000010B ;Cursor home acall LCDcom ; acall LCDrdy ; mov A,#10000000B ;set DDram Address to Home 17.12.1995 ; acall LCDcom ;falls mit DDram gearbeitet wird ajmp wait ;nach Befehl etwas warten ; ret ;da der Home Befehl bis zu 4,8ms dauern kann LCDcshiftr acall LCDrdy mov A,#00010100B ;Cursor shift right acall LCDcom djnz R1,LCDcshiftr ;in R1 steht die Cursor-position differenz ret ;Zeile 1 = 1-40, Zeile 2 = 41-80 LCDcshiftl acall LCDrdy mov A,#00010000B ;Cursor shift left acall LCDcom djnz R1,LCDcshiftl ;in R1 steht die Cursor-position differenz ret LCDxy push ACC lcall LCDrdy mov A,R2 dec A jz LCDxy_1 ;Wert ist in Zeile 1 mov A,R1 ;umschalten auf Zeile 2 orl A,#11000000B ajmp end_LCDxy LCDxy_1 mov A,R1 ;Wert von R1 sichern orl A,#10000000B end_LCDxy lcall LCDcom ;Positionieren des Cursors pop ACC ;Accu wiederherstellen ret LCDcl1 mov A,#10000000B ;Einsprung fuer Clear Line 1 lcall LCDcom mov R1,#DISPtype ;alle Positionen in Zeile loeschen mov A,#' ' ;Blank ausgeben LCDcl1_1 lcall LCDchr djnz R1,LCDcl1_1 mov A,#10000000B lcall LCDcom ret LCDcl2 mov A,#11000000B ;Einsprung fuer Clear Line 2 lcall LCDcom mov R1,#DISPtype ;alle Positionen in Zeile loeschen mov A,#' ' ;Blank ausgeben LCDcl2_1 lcall LCDchr djnz R1,LCDcl2_1 mov A,#11000000B lcall LCDcom ret LCDwait mov R0,#5 lwait1 mov R1,#0 lwait2 mov R2,#0 lwait3 nop nop djnz R2,lwait3 djnz R1,lwait2 djnz R0,lwait1 ret LCDLwait mov R0,#1 Llwait1 mov R2,#0 Llwait2 mov R3,#0 Llwait3 nop nop djnz R3,Llwait3 djnz R2,Llwait2 djnz R0,Llwait1 ret LCDitoa push DPL push DPH push ACC ; einmal fuer unterprogramm, push ACC ; einmal fuer SWAP mov DPTR,#itoatab swap A anl A,#0FH movc A,@A+DPTR lcall LCDchr pop ACC anl A,#0FH movc A,@A+DPTR lcall LCDchr pop ACC pop DPH pop DPL ret LCDitoaH push DPL ;Anzeigen High Nibble als ASCII push DPH push ACC ; einmal fuer unterprogramm, mov DPTR,#itoatab swap A anl A,#0FH movc A,@A+DPTR lcall LCDchr pop ACC pop DPH pop DPL ret LCDitoaL push DPL ;Anzeigen einzelner Character 0-F als Hex (Low Nibble) push DPH push ACC ; einmal fuer unterprogramm, mov DPTR,#itoatab anl A,#0FH movc A,@A+DPTR lcall LCDchr pop ACC pop DPH pop DPL ret itoatab db "0123456789ABCDEF" LCDLight_on setb LCD_Light ret LCDLight_off clr LCD_Light ret