;LCD8252.asm ******************************************************************************** ;***** Hilfsprogramme für die Text- und Zahlenausgabe an das LCD-Display ;***** Vor der Verwendung initialisieren mit lcall initLCD ;***** veränderte Register: r2 bis r7 der Registerbank 1 ;***** daher Stack hinter den Bitadressierbaren Bereich: mov sp,#2fh ;***** Übergaberegister ist der Akku ******************************************************** include reg_51.pdf ;Registeradressen einbinden Code ;Codesegment. Code wird vom Linker hinter andere Datei gehängt LCD_PORT EQU P0 ; *** Hier den verwendeten Port einsetzen !!!!!!!!!!!! **** !!!!!!!!!!!!!!!! public initLCD,loeschen,loeschzeile1,loeschzeile2,textzeile1,textzeile2,cursorpos public textaus,zifferaus,hexaus,dezaus,dualaus,dualaus1,dualaus2 ;---- Verwendung der Hilfsprogramme: -------------------------------------------------- ; lcall initLCD ;Initialiserung des LCD-Displays ; lcall loeschen ;gesamtes Diplay löschen ; lcall loeschzeile1 ;nur Zeile 1 des Displays löschen ; lcall loeschzeile2 ;nur Zeile 2 des Displays löschen ;*** Die 16 Zeichen belegen die Display-Adressen 00h-0Fh (Zeile1) und 40h-4Fh (Zeile2) ; mov a,#03 ;Cursor auf die 4. Anzeigestelle setzen ; lcall cursorpos ;*** Textausgaben ************* die Anfangsadresse des Textes muß *********** ;*** im DPTR stehen und der Text muß mit einer 0 abgeschlossen werden! ***** ; mov dptr,#Text1 ;Text ab der ; lcall textaus ;aktuellen Cursorposition ausgeben ; mov dptr,#Text1 ;Text ab der 1.Stelle ; lcall textzeile1 ;in Zeile 1 ausgeben ; mov dptr,#Text1 ;Text ab der 1.Stelle ; lcall textzeile2 ;in Zeile 2 ausgeben ;Text1: db 'Hallo! Test...',0 ;Angabe des auszugebenden Textes am Programmende ;*** Zahlenausgaben: Übergaberegister ist der Akku ******************************************* ; mov a,p1 ;Ausgabe des Portinhalts von P1 ; lcall zifferaus ;mit nur einer Ziffer (Lownibbel) an das Display ; mov a,p1 ;Ausgabe des Portinhalts von P1 als 2-stellige Hexzahl ; lcall hexaus ;Es werden immer 2 Stellen mit führenden Nullen ausgegeben ; mov a,p1 ;Ausgabe des Portinhalts von P1 als 3-stellige Dezimalzahl ; lcall dezaus ;Es werden immer 3 Stellen ausgegeben, führende Nullen sind dunkel ; mov a,p1 ;Ausgabe des Portinhalts von P1 als 8-Bit-Dualzahl ; lcall dualaus ;Es werden immer 8 Stellen ausgegeben mit führenden Nullen ; mov a,p1 ;Ausgabe des Portinhalts von P1 als 8-Bit-Dualzahl ; lcall dualaus1 ;rechtsbündig in Zeile1 ; mov a,p1 ;Ausgabe des Portinhalts von P1 als 8-Bit-Dualzahl ; lcall dualaus2 ;rechtsbündig in Zeile2 ;*** Anwendungsbeispiele siehe Datei LCDTEST.asm ******************************* ;****** Definitionen / Abkürzungen ************************************************ reg2 EQU 0Ah ;Register der Bank1 reg3 EQU 0Bh reg4 EQU 0Ch reg5 EQU 0Dh reg6 EQU 0Eh reg7 EQU 0Fh ; **************** Display initialisieren **************** ; ; Display arbeitet im 2*4-Bit Modus ; ; Die 16 Zeichen belegen die Display-Adressen 00-0F und 40-4F (HEX!) ; ; Bit: 7 6 5 4 3 2 1 0 ; Register Read/ 0 Takt D7/D3 D6/D2 D5/D1 D4/D0 ; Select Write initLCD: mov LCD_PORT,#00010011b ;aufwecken! Takt=1 mov LCD_PORT,#00000011b ; Takt=0 mov reg5,#10 ; ca. 5 msec warten w0: djnz reg4,w0 djnz reg5,w0 mov LCD_PORT,#00010011b ;aufwecken! Takt=1 mov LCD_PORT,#00000011b ; Takt=0 w2: djnz reg5,w2 ; wartet 100 usec mov LCD_PORT,#00010011b ;aufwecken! Takt=1 mov LCD_PORT,#00000011b ; Takt=0 w3: djnz reg5,w3 ; wartet 100 usec mov LCD_PORT,#00010010b ;8->4 BITS UMSCHALTEN, Takt=1 mov LCD_PORT,#00000010b ; Takt=0 w4: djnz reg5,w4 mov A,#00101000b ;Function set 4 bits lcall LCDbefehl ;Ausgabe im 4Bit-Modus mov A,#00001100b ; Display AN, Cursor AUS lcall LCDbefehl ;des Zeichens an der Cursorposition mov A,#00000110b ; Not Shifted Display, Increment lcall LCDbefehl ret ;*********** Loeschen Display ***************************************** loeschen: mov A,#00000001b ;Display clear lcall LCDbefehl ret ;*********** Cursor AN ************************************************ cursorAN: mov A,#00001110b ;Cursor und Display AN lcall LCDbefehl ret ;*********** Cursor AUS *********************************************** cursorAUS: mov A,#00001100b ;Cursor AUS, Display AN lcall LCDbefehl ret ;*********** Cursorposition ******************************************* cursorpos: orl a,#10000000b ;Kennung für DD RAM address set lcall LCDbefehl ret ;*********** Cursorhome *********************************************** cursorhome: mov A,#00000010b ;Cursor home lcall LCDbefehl ret ;*********** Zeile 1 löschen ****************************************** loeschzeile1: mov A,#00000010b ;Cursor home lcall LCDbefehl mov dptr,#textloesch lcall textzeile1 mov A,#00000010b ;Cursor home lcall LCDbefehl ret textloesch: DB ' ',0 ;*********** Zeile 2 löschen ****************************************** loeschzeile2: mov a,#40h lcall cursorpos ;Cursor auf Position 1.Stelle/2.Zeile mov dptr,#textloesch lcall textzeile2 mov a,#40h lcall cursorpos ;Cursor auf Position 1.Stelle/2.Zeile ret ;*********** Text an Zeile 1 ausgeben ********************************* textzeile1: mov A,#00000010b ;Cursor home lcall LCDbefehl textaus: mov reg4,#0 ;0 ins r4 => Buchstabe 0 textloop: mov A,reg4 ;Nr des Buchstabens in den Akku inc reg4 cjne a,#10h,holbuchst ;schon Maximalzahl an Buchstaben? sjmp textende ;für eine Zeile => ja => Ende holbuchst: movc A,@A+DPTR ;Text Buchstabenweise holen jz textende ;falls 0 => Ende, sonst ausgeben ausgeben: lcall LCDtext sjmp textloop textende: ret ;*********** Text an Zeile 2 ausgeben ********************************* textzeile2: mov a,#40h lcall cursorpos ;Cursor auf 1.Stelle/2.Zeile sjmp textaus ;********* Textaus (Text ab momentaner Cursorposition ausgeben ********** ;textaus2: mov a,#0 ; movc a,@a+dptr ;Text zeichenweise holen ; jz textend ;Ende wenn Ordnungszahl des zeichens=0 ; lcall LCDtext ; inc dptr ;nächstes zeichen ; sjmp textaus ;textend: ret ;********* Befehl für LCD-Display im Akku ausgeben an LCD_PORT ************** ;*************** RS R/W D7 D6 D5 D4 D3 D2 D1 D0 ;*************** 0 0 x x x x x x x x LCDbefehl: push ACC swap a ;High- und Low-Nibbel tauschen anl A,#00001111b ;4 Bits maskieren orl A,#00010000b ;Übergabetakt = 1, High-Nibbel senden mov LCD_PORT,A anl A,#00001111b ;Takt = 0 mov LCD_PORT,A pop ACC anl A,#00001111b ;Low-Nibble orl A,#00010000b ;Takt = 1 mov LCD_PORT,A anl A,#00001111b ;Takt = 0 mov LCD_PORT,A sjmp wbusy ;warten bis Bearbeitung beendet ;********* Text fr LCD-Display im Akku ausgeben an LCD_PORT ************** ;*************** RS R/W D7 D6 D5 D4 D3 D2 D1 D0 ;*************** 1 0 x x x x x x x x LCDtext: push ACC swap a ;Nibbel vertauschen anl A,#00001111b ;4 Bits maskieren orl A,#10010000b ;Übergabetakt = 1, RS = 1 (Befehl!) mov LCD_PORT,A anl A,#10001111b ;Takt = 0 mov LCD_PORT,A pop ACC anl A,#00001111b ;Low-Nibble orl A,#10010000b ;Takt = 1, RS = 1 mov LCD_PORT,A anl A,#10001111b ;Takt = 0 mov LCD_PORT,A ;************** warten bis Bearbeitung im Display beendet ********** wbusy: mov LCD_PORT,#01011111b ; Busy lesen, Takt=1, RS = 0 mov A,LCD_PORT ; und holen mov LCD_PORT,#01001111b ; Takt=0 nop mov LCD_PORT,#01011111b ; Low-Byte holen (ohne Bedeutung) mov LCD_PORT,#01001111b mov reg2,50 ;Zeitverzögerung 1ms warteR2: mov reg3,#10 ;statt auf busy warten warteR3: djnz reg3,warteR3 ;wenn LCD an p0 djnz reg2,warteR2 ; jb ACC.3,wbusy ; Busy? warten , geht nicht mit LCD an p0 ret ;*********************** dezaus ********************************************* ;+++++++++ Die Zahl im Akku wird als Dezimalzahl ausgegeben +++++++++++++++++ ;--------- Es werden immer 3 Stellen ausgegeben, führende Nullen sind dunkel dezaus: push acc mov b,#100 ;der in A stehende Wert wird durch 100 div ab ;geteilt und die Hunderter-Ziffer in mov reg7,a ;r7 gegeben mov a,b ;die verbleibende Zehnerzahl mov b,#10 ;wird durch 10 div ab ;geteilt swap a ;Die Zehnerziffer wird das High-Nibbel, add a,b ;die Einerziffer das Low-Nibbel mov reg5,a ;diese BCD-Zahl wird in r5 gespeichert mov a,reg7 ;die vorderste BCD-Ziffer mov reg4,a ;wird in r4 gesichert und jnz ausg1 ;wird normal ausgegeben, falls sie nicht 0 ist mov a,#31 ;leere Anzeige lcall lcdtext ;falls null sjmp Ziff2 ausg1: lcall sendascii ;1.Ziffer ausgeben Ziff2: mov a,reg5 ;2. u. 3. Ziffer zurückholen hex0: mov reg7,a ;zwischenspeichern in r7 anl a,#0f0h ;High-Nibbel maskieren swap a ;und zur Ziffer im Low-Nibbel machen jnz ausg2 ;wird normal ausgegeben, falls sie nicht 0 ist cjne a,reg4,ausg2 ;nur 0 unterdrücken falls 1.Ziffer auch 0 war mov a,#31 ;leere Anzeige lcall lcdtext ;falls null sjmp Ziff3 ausg2: lcall sendascii ;2.Ziffer ausgeben Ziff3: mov a,reg7 ;Zwischengespeicherte Zahl zurck anl a,#0fh ;Low-Nibbel ausblenden lcall sendascii ;und ausgeben dezend: pop acc ret ;*********************** hexaus ***************************************** ;+++++++++ Die Zahl im Akku wird hexadezimal ausgegeben +++++++++++++++++ ;--------- Es werden immer 2 Stellen mit führenden Nullen ausgegeben ---- hexaus: push acc mov reg7,a ;zwischenspeichern in r7 anl a,#0f0h ;High-Nibbel maskieren swap a ;und zur Ziffer im Low-Nibbel machen ; cjne a,#0,ausg2Z ;zur Unterdrückung der führenden Null ; mov a,#20 ;leere Anzeige ; lcall lcdtext ; ; sjmp weit2 ; ausg2Z: lcall sendascii ; weit2: mov a,reg7 ;Zwischengespeicherte Zahl zurck anl a,#0fh ;Low-Nibbel ausblenden lcall sendascii ;und ausgeben pop acc ret ;****************** dualaus (Zahl im Akku als 8-Bit-Dualzahl ausgeben) ******** dualaus: push acc mov reg5,#8 ;Zähler dloop: mov reg7,a ;Zahl zwischenspeichern jb acc.7,d1 ;Sprung zur "1"-Ausgabe wenn Bit=1 mov a,#0 ;Null ausgeben lcall sendascii ; sjmp d2 ; d1: mov a,#1 ;Eins ausgeben lcall sendascii ; d2: mov a,reg7 ;zwischengespeicherte Zahl zurück rl a ;nächstes Bit djnz reg5,dloop ;von vorne falls noch nicht alle 8 Bit pop acc ret ;***************** Duale Ausgabe rechtsbündig in Zeile 1 ********************* dualaus1: push acc mov a,#08 lcall cursorpos pop acc lcall dualaus ret ;***************** Duale Ausgabe rechtsbündig in Zeile 2 ********************* dualaus2: push acc mov a,#48 lcall cursorpos pop acc lcall dualaus ret ;************** sendascii (1 Hexziffer als Ascii-Zeichen senden) ********* sendascii: mov reg6,a subb a,#0Ah mov a,reg6 jc zahl Buchst: add a,#37h sjmp weit1 zahl: clr c ;Carry zurcksetzen, sonst Fehler bei add add a,#30h weit1: lcall LCDtext ret ;*************** zifferaus (eine Ziffer 0 bis 9 ausgeben ***************** zifferaus: push acc anl a,#0Fh lcall sendascii pop acc ret ;****** PIN-Belegung für LCD-Display LTN 214 R-10 am LCD_PORT ************** ; * Uebertragung eines Bytes als 2 * 4 Bits. ; * Ansicht von oben auf Display ; * 1 GND--------------------------------------------------> GND ; * 2 +5Volt-----------------------------------------------> +5V ; * 3 V0: Steuerspannung Kontrast 0..5 Volt erlaubt,-------> V0 ; * Arbeitspunkt ca. 0.6 V (am besten Spindeltrimmer zum Einst.) ; * 4 RS: Registersatz (Display oder Befehl)---------------> LCD_PORT.7 ; * 5 R/W: Schreiben oder lesen----------------------------> LCD_PORT.6 ; * 6 E: Uebergabetakt-------------------------------------> LCD_PORT.4 ; * 7-10: frei (eigentlich D0 - D3, wird aber nicht verwendet) ; * 11: D4/D0----------------------------------------------> LCD_PORT.0 ; * 12: D5/D1----------------------------------------------> LCD_PORT.1 ; * 13: D6/D2----------------------------------------------> LCD_PORT.2 ; * 14: D7/D3----------------------------------------------> LCD_PORT.3 ; ******************************************************* END