Pfad: Home => AVR-DE => Anwendungen => LCD-Experimentierboard => Include-Routinen-Quellcode   This page in English: Flag EN Logo
tn24_lcd_Experimentierboard klein Anwendungen von
AVR-Einchip-Prozessoren AT90S, ATtiny, ATmega und ATxmega
Experimentierboard mit einem ATtiny24/44/84 und einer LCD Include-Routinen-Quellcode

LCD-Include-Routinen in Assembler für das ATtiny24/44/84-Experimentierboard

Quellcode-Link: hier. Diese Version ist auf eine LCD mit 4 Zeilen und 20 Zeichen pro Zeile eingestellt.

Die hier beschriebene LCD-Routine ist durch eine verbesserte Version ersetzt und veraltet! Hier gibt es eine universell anwendbare Lösung, die auch für die hier beschriebene Hardware angepasst werden kann.

;
; ************************************************
; * Include Code zur 4-Bit-Ansteuerung einer LCD *
; * im Busy-Flag-Modus, mit Basisroutinen        *
; * (C)2018 by www.avr-asm-tutorial.net          *
; ************************************************
;
; Der Include-Code enthaelt Basisroutinen fuer die
; 4-Bit-Ansteuerung einer 1*8-LCD am ATtiny24 im
; Busy-Modus (bidirektionaler Datenbus).
; Die Routine LcdInit
; - inittiert die Ports und die LCD,
; - gibt eine Init-Meldung auf der LCD aus,
; - wartet cLcdDelay (in 250 ms), und
; - gibt eine Ausgabemaske auf der LCD aus.
; Der Text der Ausgabemaske steht am Ende der
; Include-Datei und kann eingestellt werden.
;
; ------ Einstellungen zum Displaytyp ------------
;
.equ cLcdLines = 4 ; Anzahl Zeilen der LCD
.equ cLcdColumns = 20 ; Anzahl Zeichen pro Zeile
;
; ---- Einstellungen der LCD-Ports und Pins ------
;
; LCD-Kontrollport
.equ pLcdCO   = PORTB  ; LCD-Kontrollport-Ausgabe
.equ pLcdCD   = DDRB   ; LCD-Kontrollport-Richtung
.equ bLcdCOE  = PORTB2 ; LCD Enable Pin Output
.equ bLcdCDE  = DDB2   ; LCD Enable Pin Richtung
.equ bLcdCORS = PORTB0 ; LCD RS Pin Output
.equ bLcdCDRS = DDB0   ; LCD RS Pin Richtung
.equ bLcdCORW = PORTB1 ; LCD R/W Pin Output
.equ bLcdCDRW = DDB1   ; LCD R/W Pin Richtung
; LCD-Datenport
.equ pLcdDO   = PORTA  ; LCD-Datenport-Ausgabe
.equ pLcdDI   = PINA   ; LCD-Datenport-Eingabe
.equ pLcdDD   = DDRA   ; LCD-Datenport-Richtung
.equ mLcdDRW  = 0xF0   ; LCD-Datenport-Maske Schreiben
.equ mLcdDRR  = 0x0F   ; LCD-Datenport-Maske Lesen
;
; -------- Verwendete Register -------------------
;
; Das angegebene Register ist im Hauptprogramm
; zu definieren:
;
; rmp (ab R16)
;
; --- Stellt folgende Basisroutinen zur Verfuegung -----
;
; Die folgenden Routinen werden zur Verfuegung ge-
; stellt:
;   Register: Chgd: Inhalt bleibt nicht erhalten
;             Used: Register wird benutzt, Wert
;                   wird wieder hergestellt
; Routine  Macht        Aufrufparameter      Register
; -------  ------------ -------------------- ----------
; LcdInit  Initiieren   Keine                rmp:Chgd
;                                            ZH:ZL:Used
; LcdText  Gib den Text ZH:ZL Texttabelle    rmp:Chgd
;          im Flash in  0D=Naechste Zeile    R0,R1:Used
;          der Tabelle  FF=Ignoriere         ZH:ZL:Chgd
;          in Zeile 1   FE=Ende Tabelle
;          aus
; LcdTextC Gib den Text (wie LcdText)        (wie LcdText)
;          im Flash an
;          der aktuellen
;          Position aus
; LcdSRam  Gib den Text XH:XL: zeigt auf     rmp:Chgd
;          im SRAM aus  Position im SRAM     XH:XL:Chgd
;                       ZH:ZL: Lcd-Position  ZH:ZL:Chgd
;                       rmp: Anzahl Zeichen  R0:Used
; LcdPos   Setze Ausga- ZH: Zeile 0..3       rmp:Chgd
;          beposition   ZL: Spalte 0..19     
; LcdLine  Zeile ein-   rmp: Zeile 0..3      rmp:Chgd
;          stellen,
;          Spalte=0
; LcdLineN Zeile ein-   N: Zeile 1..4        rmp:Chgd
;          stellen,
;          Spalte=0
; LcdChar  Gib ASCII-   rmp:ASCII-Zeichen    rmp:Chgd
;          Zeichen aus                       ZL:Used
; LcdCtrl  Gib Kontroll- rmp: Kontroll-      rmp:Chgd
;          Befehl aus    zeichen             ZL:Used
; LcdChars Erzeuge ei-  ZH:ZL Zeichentabelle rmp:Chgd
;          gene Zeichen                      R0,R1:Used
;                                            ZH:ZL:Chgd
;
; ---------- Optionale Routinen -----------
;
; Stellt bei Bedarf folgende optionalen Routinen zur
; Verfuegung:
;
; Schalter  Routine  Fuehrt aus   Parameter Register
; --------  -------- ------------ --------- --------
; sLcdDec8  LcdDec8  8-Bit-Bin zu rmp:Bin   rmp:Chgd
;                    Dezimal (3             R0,R1,ZL:
;                    Stellen)                 Used
; sLcdDec16 LcdDec16 16-Bit-Bin   ZH:ZL:Bin rmp:Chgd
;                    zu Dezimal             R0,R1,R2:
;                    (5 Stellen)              Used
; sLcdHex8  LcdHex8  8-Bit-Bin zu rmp:Bin   rmp:Chnd
;                    Hex (2 Stel-
;                    len)
; sLcdHex16 LcdHex16 16-Bit-Bin   ZH:ZL:Bin rmp:Chgd
;                    zu Hex (4
;                    Stellen)
; sLcdBin8  LcdBin8  8-Bit-Bin    rmp:Bin   rmp:Chgd
;                    zu Binaer              ZH:ZL:Used
;                    (8 Stellen)
; sLcdBin16 LcdBin16 16-Bit-Bin   ZH:ZL:Bin rmp:Chgd
;                    zu Binaer              ZH:ZL:Used
;                    (16 Stellen)
;
; --------- LCD-Ansteuerung Init ----------
;
LcdInit:
  ; Init I/O-Ports und -Pins
  cbi pLcdCO,bLcdCOE ; Enable = 0
  sbi pLcdCD,bLcdCDE ; Enable = Output
  cbi pLcdCO,bLcdCORS ; RS-Pin = 0
  sbi pLcdCD,bLcdCDRS ; RS-Pin = Output
  cbi pLcdCO,bLcdCORW ; RW-Pin = 0
  sbi pLcdCD,bLcdCDRW ; RW-Pin = Output
  in rmp,pLcdDD ; Lese Richtungsbits Datanport
  ori rmp,mLcdDRW ; Datenport-Ausgabemaske, Schreiben
  out pLcdDD,rmp ; auf Ausgabe
  ; Warte 50 ms bis LCD hochgefahren ist
  rcall Warte50ms ; Karenzzeit 50 ms
  ; Versetze in 8-Bit-Modus (drei Mal)
  ldi rmp,0x30 ; 8-Bit-Modus
  rcall LcdC8Byte ; Schreibe im 8-Bit-Mode
  rcall Warte5ms ; Warte 5 ms
  ldi rmp,0x30
  rcall LcdC8Byte
  rcall Warte5ms
  ldi rmp,0x30
  rcall LcdC8Byte
  rcall Warte5ms
  ; Umstellung auf 4-Bit-Modus
  ldi rmp,0x20 ; Schalte in 4-Bit-Modus um
  rcall LcdC8Byte
  rcall Warte5ms
  ; Funktionseinstellungen LCD
  .if cLcdLines == 1
    ldi rmp,0x20 ; 4-Bit-Modus, 1 Zeile, 5*7
    .else
    ldi rmp,0x28 ; 4-Bit-Modus, 4 Zeilen, 5*7
    .endif
  rcall LcdCtrl ; Byte an Kontrollregister LCD
  ldi rmp,0x0F ; Display ein, Blinken
  rcall LcdCtrl ; Byte an Kontrollregister LCD
  ldi rmp,0x01 ; Display loeschen
  rcall LcdCtrl ; Byte an Kontrollregister LCD
  ldi rmp,0x06 ; Autoindent
  rcall LcdCtrl ; Byte an Kontrollregister LCD
  ldi ZH,High(2*LcdTxtInit)
  ldi ZL,Low(2*LcdTxtInit)
  rcall LcdText ; Text ausgeben auf LCD
  ldi rmp,0x0C ; Cursor und Blink aus
  rcall LcdCtrl
  ldi rmp,5*cLcdDelay ; Verzoegerung laden
LcdInit1:
  rcall Warte50ms ; 50 ms verzoegern
  dec rmp
  brne LcdInit1
  ldi ZH,High(2*LcdTxtMsk)
  ldi ZL,Low(2*LcdTxtMsk)
  rcall LcdText ; Maske ausgeben
  ldi rmp,0x0C ; Cursor und Blink aus
  rcall LcdCtrl
  ret
;
; Ausgabe von Text im Flash ab Zeile 1 der LCD
;   Z zeigt auf den Text im Flash
;   Steuerzeichen:
;     0xFE: Ende der Ausgabe
;     0xFF: Fuellzeichen (keine Ausgabe)
;     0x0D: Naechste Zeile
;
LcdText:
  rcall LcdLine1 ; auf Zeile 1
LcdTextC: ; Setze an aktuelle Position fort
  push R0 ; Sichern R0
  clr R0 ; Zeilenzaehler
LcdText1:
  lpm rmp,Z+ ; lese Zeichen aus Flash
  cpi rmp,0xFE ; Ende Ausgabe?
  breq LcdTextRet ; nein
  cpi rmp,0xFF ; Fuellzeichen?
  breq LcdText1 ; ja, naechstes Zeichen
  cpi rmp,0x0D ; Zeilenwechsel?
  brne LcdText2 ; Kein Zeilenwechsel
  inc R0 ; Naechste Zeile
  mov rmp,R0 ; Setze Zeile
  cpi rmp,cLcdLines ; Ende der LCD?
  brcc LcdTextRet ; Ja, beende Ausgabe
  rcall LcdLine ; Stelle Zeile ein
  rjmp LcdText1 ; weiter mit Zeichen
LcdText2: ; Ausgabe Zeichen
  rcall LcdChar ; Zeichen ausgeben
  rjmp LcdText1 ; und weiter
LcdTextRet:
  pop R0 ; Stelle R0 wieder her
  ret ; Fertig
;
; Ausgabe von Text im SRAM auf dem LCD
;   ZH = Zeile 0..3; ZL = Spalte 0..19,
;   XH:XL = Adresse im SRAM, rmp: Anzahl
;
LcdSram:
  push R0
  mov R0,rmp ; kopieren Anzahl
  rcall LcdPos ; setze LCD-Position
LcdSram1:
  ld rmp,X+ ; lese Ausgabe-Byte
  rcall LcdChar ; auf LCD ausgeben
  dec R0 ; Zaehler abwaerts
  brne LcdSram1 ; noch Zeichen
  pop R0
  ret ; Fertig
;
; Setzt den Ausgabecursor auf den
; Zeilenanfang der ausgewaehlten Zeile
;   Zeile: rmp 0 .. 3 
LcdLine:
  cpi rmp,1 ; Zeile 2?
  brcs LcdLine1 ; nach Zeile 1
.if cLcdLines > 1
  breq LcdLine2 ; nach Zeile 2
  .if cLcdLines > 2
    cpi rmp,2 ; Zeile 3?
    breq LcdLine3 ; nach Zeile 3
    .if cLcdLines > 3
      rjmp LcdLine4 ; nach Zeile 4
	  .endif
    .endif
  .endif
LcdLine1:
  ldi rmp,0x80 ; Zeile 1
  rjmp LcdCtrl ; Ausgabe Kontrollwort
.if cLcdLines > 1
  LcdLine2:
    ldi rmp,0xC0 ; Zeile 2
    rjmp LcdCtrl ; Ausgabe Kontrollwort
  .if cLcdLines > 2
    LcdLine3:
      ldi rmp,0x80+cLcdColumns ; Zeile 3
      rjmp LcdCtrl ; Ausgabe Kontrollwort
    .if cLcdLines > 3
      LcdLine4:
        ldi rmp,0xC0+cLcdColumns ; Zeile 4
        rjmp LcdCtrl ; Ausgabe Kontrollwort
      .endif
    .endif
  .endif
  ret
;
; Setzt den Ausgabecursor auf die Position
; in ZH:ZL, ZH ist Zeile (0..3), ZL ist Spalte
;
LcdPos:
  ldi rmp,0x80 ; Setze Zeile 1
  cpi ZH,1 ; Zeile 2?
  brcs LcdPos1 ; Zeile = 1
  ldi rmp,0xC0 ; Setze Zeile 2
  breq LcdPos1 ; Zeile = 2
  ldi rmp,0x80+20 ; Setze Zeile 3
  cpi ZH,2 ; Zeile 3?
  breq LcdPos1 ; Zeile = 3
  ldi rmp,0xC0+20 ; Zeile = 4
LcdPos1:
  add rmp,ZL ; addiere Spalte
  rjmp LcdCtrl ; Ausgabe Kontrollwort
;
; Eigene Zeichen definieren
;   Zeiger auf Zeichentabelle in ZH:ZL
;   Benutzt: R0,R1 (wird wieder hergestellt)
;   Aendert: rmp
;
LcdChars:
  push R0 ; R0 retten
  push R1 ; R1 retten
LcdChars1:
  lpm ; Lese Adresse
  tst R0 ; auf Null pruefen
  breq LcdChars3 ; fertig
  adiw ZL,2 ; ueberlese Fuellbyte
  ldi rmp,8
  mov R1,rmp
LcdChars2:
  mov rmp,R0 ; Adresse setzen
  rcall LcdCtrl ; an LCD
  lpm rmp,Z+ ; lese Daten
  rcall LcdChar ; Ausgabe an LCD
  inc R0 ; Adresse erhoehen
  dec R1 ; Zaehler abwaerts
  brne LcdChars2 ; noch welche
  rjmp LcdChars1 ; naechstes Zeichen
LcdChars3:
  pop R1
  pop R0
  ret ; fertig
;
; Makro LcdEDly taktabhaengige Verzoegerung
;
.Macro LcdEDly
  nop ; ein Takt warten
  .if clock > 1000000 ; Takt groesser 1 MHz
    nop ; noch ein Takt warten
    .if clock > 2000000 ; Takt groesser 2 MHz
      nop ; noch zwei Takte warten
      nop
      .if clock > 4000000 ; Takt groesser 4 MHz
        nop ; noch vier Takte warten
        nop
        nop
        nop
        .endif
      .endif
    .endif
  .endm
;
; Datenwort-Ausgabe im 4-Bit-Modus
;   Daten in rmp
;
LcdChar:
  rcall LcdBusy ; warte bis busy = Null
  sbi pLcdCO,bLcdCORS ; setze RS-Bit
  rjmp Lcd4Byte ; gib Byte in rmp aus
;
; Kontrollwort-Ausgabe im 4-Bit-Modus
;   Daten in rmp
;
LcdCtrl:
  rcall LcdBusy ; warte bis busy = Null
  cbi pLcdCO,bLcdCORS ; loesche RS-Bit
;
; Ausgabe Byte im 4-Bit-Modus mit Busy
;   Daten in rmp
;   verwendet ZL, stellt Inhalt wieder her
;
Lcd4Byte:
  push ZL ; Sichern ZL
  push rmp ; rmp auf Stapel legen
  andi rmp,0xF0 ; unteres Nibble loeschen
  in ZL,pLcdDO ; Lese Data-Input-Port
  andi ZL,0x0F ; oberes Nibble loeschen
  or rmp,ZL ; unteres und oberes Nibble
  out pLcdDO,rmp ; an Datenport LCD
  nop ; ein Takt warten
  sbi pLcdCO,bLcdCOE ; LCD-Enable aktivieren
  LcdEDly ; Verzoegerung einfuegen
  cbi pLcdCO,bLcdCOE ; LCD-Enable aus
  pop rmp ; rmp wieder herstellen
  andi rmp,0x0F ; oberes Nibble loeschen
  swap rmp ; Nibble vertauschen
  or rmp,ZL ; unteres und oberes Nibble
  out pLcdDO,rmp ; an Datenport LCD
  nop ; ein Takt warten
  sbi pLcdCO,bLcdCOE ; LCD-Enable aktivieren
  LcdEDly ; taktabhaengig warten
  cbi pLcdCO,bLcdCOE ; LCD-Enable aus
  pop ZL
  ret ; fertig
;
; Warte bis Busy Null
;   Benutzt rmp und ZL, Inhalt wird erhalten
;
LcdBusy:
  push ZL ; rette ZL
  push rmp ; rette rmp
  in rmp,pLcdDD
  andi rmp,mLcdDRR ; Lesemaske
  out pLcdDD,rmp ; in Richtungsregister
  cbi pLcdCO,bLcdCORS ; loesche RS
  sbi pLcdCO,bLcdCORW ; R/W setzen
LcdBusy1:
  sbi pLcdCO,bLcdCOE ; setze LCD-Enable
  LcdEDly ; taktabhaengig warten
  in ZL,pLcdDI ; lese oberes Nibble
  cbi pLcdCO,bLcdCOE ; loesche LCD-Enable
  andi ZL,0xF0 ; unteres Nibble loeschen
  sbi pLcdCO,bLcdCOE ; setze LCD-Enable
  LcdEDly ; taktabhaengig warten
  in rmp,pLcdDI ; lese unteres Nibble
  cbi pLcdCO,bLcdCOE ; loesche LCD-Enable
  andi rmp,0xF0 ; loesche unteres Nibble
  swap rmp ; oberes/unteres Nibble tauschen
  or ZL,rmp ; oberes und unteres Nibble
  sbrc ZL,7 ; ueberspringe bei Busy=0
  rjmp LcdBusy1 ; wiederhole bis Busy=0
  cbi pLcdCO,bLcdCORW ; R/W loeschen
  in rmp,pLcdDD
  ori rmp,mLcdDRW
  out pLcdDD,rmp ; in Richtungsregister
  pop rmp ; rmp wieder herstellen
  pop ZL
  ret ; zurueck
;
; Kontrollwort-Ausgabe im 8-Bit-Modus
;   Datenbyte in rmp
;   Verwendet ZL, stellt Inhalt wieder her
;
LcdC8Byte:
  cbi pLcdCO,bLcdCORS ; RS-Bit loeschen
  andi rmp,0xF0 ; unteres Nibble loeschen
  in ZL,pLcdDO ; Lese Data-Input-Port
  andi ZL,0x0F ; oberes Nibble loeschen
  or rmp,ZL ; unteres und oberes Nibble
  out pLcdDO,rmp ; an Datenport LCD
  nop ; ein Takt warten
  sbi pLcdCO,bLcdCOE ; LCD-Enable aktivieren
  LcdEDly ; taktabhaengig warten
  cbi pLcdCO,bLcdCOE ; LCD-Enable aus
  ret ; fertig
;
; ------- Optionale Routinen ------------
;
; 8-Bit-Dezimalzahl an aktueller Position
;   auf der LCD ausgeben
;   Schalter: sLcdDec8
;   Parameter: 8-Bit-Binaerzahl in rmp
.ifdef sLcdDec8
  LcdDec8:
    push ZL
    push R0
    push R1
    clr ZL
    mov R0,rmp
    ldi rmp,100
    rcall LcdSub8
    ldi rmp,10
    rcall LcdSub8
    ldi rmp,'0'
    add rmp,R0
    rcall LcdChar
    pop R1
    pop R0
    pop ZL
    ret
  LcdSub8:
    clr R1
  LcdSub8a:
    sub R0,rmp
    brcs LcdSub8b
    inc R1
    rjmp LcdSub8a
  LcdSub8b:
    add R0,rmp
    ldi rmp,'0'
    add rmp,R1
    cpi rmp,'0'
    brne LcdSub8c
    sbrs ZL,0
    ldi rmp,' '
    rjmp LcdSub8d
  LcdSub8c:
    ldi ZL,1
  LcdSub8d:
    rcall LcdChar
    ret
  .endif
;
; 16-Bit-Dezimalzahl an aktueller Position auf
;    der LCD ausgeben
;    Schalter: sLcdDec16
;    Aufruf: LcdDec16
;    Parameter: ZH:ZL:Binaerzahl
.ifdef sLcdDec16
  LcdDec16:
    push R0 ; Verwendete Register sichern
    push R1
    push R2
    mov R1,ZH ; MSB kopieren
    mov R0,ZL ; LSB kopieren
    clr R3 ; R3 dient zur Unterdrueckung fuehrender Nullen
    ldi ZH,High(10000) ; Zehntausender
    ldi ZL,Low(10000)
    rcall LcdSub16
    ldi ZH,High(1000) ; Tausender
    ldi ZL,Low(1000)
    rcall LcdSub16
    ldi ZH,High(100) ; Hunderter
    ldi ZL,Low(100)
    rcall LcdSub16
    ldi ZH,High(10) ; Zehner
    ldi ZL,Low(10)
    rcall LcdSub16
    ldi rmp,'0'
    add rmp,R0
    rcall LcdChar
    pop R2 ; Verwendete Register wieder herstellen
    pop R1
    pop R0
    ret
  LcdSub16:
    ldi rmp,'0' ; rmp ist Zaehler
  LcdSub16a:
    sub R0,ZL ; Subtrahiere LSB Dezimale
    sbc R1,ZH ; dto., MSB mit Carry
    brcs LcdSub16b
    inc rmp
    rjmp LcdSub16a
  LcdSub16b:
    add R0,ZL
    adc R1,ZH
    cpi rmp,'0'
    breq LcdSub16c
    inc R3 ; Keine Unterdrueckung fuehrender Nullen
  LcdSub16c:
    tst R3 ; Fuehrende Null unterdruecken?
    brne LcdSub16d
    ldi rmp,' ' ; Unterdruecken
  lcdSub16d:
    rjmp LcdChar
  .endif
;
; 16-Bit-Binaerzahl auf LCD ausgeben
;   Schalter: sLcdBin16
;   Aufruf: LcdBit16
;   Parameter: ZH:ZL: Binaerzahl
;   Register: verwendet und aendert rmp
;
.ifdef sLcdBin16
  .set sLcdBin8=1 ; Bin8-Ausgabe einschalten
  LcdBin16:
    mov rmp,ZH ; MSB kopieren
    rcall LcdBin8 ; 8 Bit binaer ausgeben
    mov rmp,ZL ; LSB kopieren
    rjmp LcdBin8
    ret
  .endif
;
; 8-Bit-Binaerzahl auf LCD ausgeben
;   Schalter: sLcdBin8
;   Aufruf: LcdBin8
;   Parameter: rmp: Binaerzahl
;   Register: verwendet und aendert rmp
;             verwendet ZH und ZL und stellt wieder her
;
.ifdef sLcdBin8
  LcdBin8:
    push ZH ; Z retten
    push ZL
    mov ZL,rmp ; Zahl kopieren
    ldi ZH,8 ; Anzahl Bits
  LcdBin8a:
    ldi rmp,'0'
    lsl ZL
    brcc LcdBin8b
    ldi rmp,'1'
  LcdBin8b:
    rcall LcdChar
    dec ZH
    brne LcdBin8a
    pop ZL ; Z wieder herstellen
    pop ZH
    ret
  .endif
;
; 16-Bit-Hexadezimalzahl an aktueller Position
;   auf der LCD ausgeben
;   Schalter: sLcdHex16
;   Parameter: 16-Bit-Binaerzahl in ZH:ZL
;   Benutzt und veraendert: rmp
;
.ifdef sLcdHex16
  .set sLcdNibble=1
  .set sLcdHex8=1
  LcdHex16:
    mov rmp,ZH ; MSB in rmp kopieren
    rcall LcdHex8 ; MSB in hex ausgeben
    mov rmp,ZL ; LSB in rmp kopieren
    rjmp LcdHex8 ; LSB in hex ausgeben
  .endif
;
; 8-Bit-Hexadezimalzahl an aktueller Position
;   auf der LCD ausgeben
;   Schalter: sLcdHex8
;   Parameter: 8-Bit-Binaerzahl in rmp
.ifdef sLcdHex8
  .set sLcdNibble=1 ; Nibble-Ausgabe einschalten
  LcdHex8:
    push rmp ; Byte in rmp retten
    swap rmp ; oberes und unteres Nibble tauschen
    rcall LcdNibble ; unteres Nibble ausgeben
    pop rmp ; rmp wieder herstellen
    rjmp LcdNibble ; unteres Nibble ausgeben
  .endif
;
; Gibt unteres Nibble in rmp in hex auf LCD aus
.ifdef sLcdNibble
  LcdNibble:
    andi rmp,0x0F ; unteres Nibble isolieren
    subi rmp,-'0' ; ASCII-0 dazu addieren
    cpi rmp,'9'+1 ; Ziffern A bis F?
    brcs LcdNibble1 ; nein
    subi rmp,-7 ; addiere 7 fuer A bis F
  LcdNibble1:
    rjmp LcdChar ; Byte in rmp auf LCD
  .endif
;
; ------ Warteroutinen ------------------
;
Warte50ms: ; Warteroutine 50 ms
.equ c50ms = 50000
.equ n50ms = clock/1000000*(c50ms-16)/4
;   rcall: + 3
  push ZH ; + 2
  push ZL ; + 2
.if clock > 4000000
  ldi ZH,HIGH(n50ms/2)
  ldi ZL,LOW(n50ms/2)
Warte50ms1:
  sbiw ZL,1
  brne Warte50ms1
  ldi ZH,HIGH(n50ms/2)
  ldi ZL,LOW(n50ms/2)
  rjmp Warte
  .else
  ldi ZH,HIGH(n50ms) ; + 1
  ldi ZL,LOW(n50ms) ; + 1
  rjmp Warte ; + 2, gesamt = 11
  .endif
Warte5ms: ; Warteroutine 5 ms
.equ c5ms = 5000
.equ n5ms = clock/1000000*(c5ms-16)/4
  push ZH
  push ZL
  ldi ZH,HIGH(n5ms)
  ldi ZL,LOW(n5ms)
  rjmp Warte
; Warteroutine Z Takte
Warte: ; Warteschleife, Takte = 4*(n-1)+11 = 4*n + 7
  sbiw ZL,1 ; + 2
  brne Warte ; + 1 / 2
  pop ZL ; + 2
  pop ZH ; +2
  ret ; + 4, Gesamt=4*n+18
;
; -------- Eroeffnungsmeldungen -------------
;
.if  cLcdColumns == 8
  LcdTxtInit:
    .db "tn24_lcd",0x0D,0xFF
    .db "avr-asm ",0x0D,0xFF
    .db "LcdInit ",0x0D,0xFF
    .db "-Start- ",0xFE,0xFE
  .endif
.if cLcdColumns == 16
  LcdTxtInit:
    .db "tn24_lcd-Modul01",0x0D,0xFF
    .db "avr-asm-tutorial",0x0D,0xFF
    .db "* Init - Phase *",0x0D,0xFF
    .db "(C)2018 DG4FAC  ",0xFE,0xFF
  .endif
.if cLcdColumns == 20
  LcdTxtInit:
    .db "tn24_lcd-Modul V 0.1",0x0D,0xFF
    .db "avr-asm-tutorial.net",0x0D,0xFF
    .db "  * Init - Phase *  ",0x0D,0xFF
    .db " (C)2018 by DG4FAC  ",0xFE,0xFF
  .endif
.if cLcdColumns == 24
  LcdTxtInit:
    .db "  tn24_lcd-Modul V 0.1  ",0x0D,0xFF
    .db "  avr-asm-tutorial.net  ",0x0D,0xFF
    .db "  * LCD-Init - Phase *  ",0x0D,0xFF
    .db "   (C)2018 by DG4FAC    ",0xFE,0xFF
  .endif
;
; ------- Ausgabemasken ----------------------
;
.if cLcdColumns == 8
  LcdTxtMsk:
    .db "Zeile 1 ",0x0D,0xFF
    .db "Zeile 2 ",0x0D,0xFF
    .db "Zeile 3 ",0x0D,0xFF
    .db "Zeile 4 ",0xFE,0xFF
  .endif
.if cLcdColumns == 16
  LcdTxtMsk:
    .db "Zeile 1         ",0x0D,0xFF
    .db "Zeile 2         ",0x0D,0xFF
    .db "Zeile 3         ",0x0D,0xFF
    .db "Zeile 4         ",0xFE,0xFF
  .endif
.if cLcdColumns == 20
  LcdTxtMsk:
    .db "Zeile 1             ",0x0D,0xFF
    .db "Zeile 2             ",0x0D,0xFF
    .db "Zeile 3             ",0x0D,0xFF
    .db "Zeile 4             ",0xFE,0xFF
  .endif
.if cLcdColumns == 24
  LcdTxtMsk:
    .db "Zeile 1                 ",0x0D,0xFF
    .db "Zeile 2                 ",0x0D,0xFF
    .db "Zeile 3                 ",0x0D,0xFF
    .db "Zeile 4                 ",0xFE,0xFF
  .endif
;
; Ende Include
;




Seitenanfang




Lob, Tadel, Fehlermeldungen, Genöle und Geschimpfe oder Spam bitte über das Kommentarformular an mich.

©2018 by http://www.avr-asm-tutorial.net