; ************************************************************** ; * Include-Datei fuer LCD-Routinen Akkuload, Version 0.1 02/05* ; * (C)2005 by Gerhard Schmidt, info@avr-asm-tutorial.net * ; ************************************************************** ; ; -------------------------------------------------------------- ; Routine Register Funktion ; -------------------------------------------------------------- ; LcdInit rmp,R0,Z Initiiert das LCD-Display zu Beginn auf: ; 8-Bit-Interface, 4 Zeilen, kein Shift, ; aktiver Cursor und blinkend ; LcdR0 rmp gibt das Zeichen in R0 auf der aktuellen ; Position des LCD aus, R0 bleibt erhalten ; LcdChar rmp,R0 gibt das Zeichen in rmp auf der aktuellen ; Position des LCD aus, rmp wird geaendert, ; Zeichen bleibt in R0 erhalten ; LcdDisplZ rmp,R0,Z gibt den Text im Flash ab Z auf der LCD ; aus, stoppt beim NULL-Zeichen ; LcdLine rmp setzt die Ausgabe der LCD auf die Zeile ; in rmp, erwartet 0..3 in rmp fuer die ; Zeilen 1..4 ; LcdLineCl rmp,R0,Z loescht die Zeile des LCD, auf die rmp ; zeigt, durch Schreiben von Leerzeichen ; LcdPos rmp,Z setzt die LCD auf die Position in Z, ; ZH ist die Zeile, ZL ist die Position in ; dieser Zeile (0..19) ; LcdMClr rmp loescht den Menueteil und setzt die ; Position in dieser Zeile auf den Anfang ; LcdMStrt rmp,R0,Z Setzt die LCD Cursor Position auf den ; Menueanfang ; LcdCursor rmp,Z Setzt den LCD-Cursor auf seine korrekte ; Position nach Ausgaben,Position<8: zeigt ; Menueausgabe 1 an ; LcdHex2 rmp Schreibt den Inhalt von rmp in Hex an die ; aktuelle LCD-Position (debug) ; LcdDec5 rmp,R0,Z schreibt die Binaerzahl in R3:R2 als ; LcdDec4 Dezimalzahl an die aktuelle LCD-Position, ; LcdDec3 5, 4, 3 oder 2 Ziffern werden angezeigt ; LcdDec2 ; -------------------------------------------------------------- ; ; Konstanten ; .EQU pLcdCO = PORTD .EQU pLcdCD = DDRD .EQU pLcdCI = PIND .EQU pLcdDO = PORTB .EQU pLcdDD = DDRB .EQU pLcdDI = PINB .EQU bLcdE = 2 ; E-Eingang des Displays .EQU bLcdRw = 3 ; Read/Write Kontrolle des Display .EQU bLcdRs = 4 ; Register Select des Display ; ; Verzoegerungsroutinen fuer die Display-Initiierung ; Anzahl der Takte einschlieszlich rcall: 3+7+4*Z-4+7 = 4*Z+13 ; Verzoegerung in Mikrosekunden: (4*Z+13)/8 ; Berechnung von Z = (8*t[µs]-13)/4 ; ; Verzoegerung 15 ms ; .EQU cLcdWt15000 = (8*15000-13)/4 ; = 29996 LcdWt15000: ldi ZH,HIGH(cLcdWt15000) ; 1 ldi ZL,LOW(cLcdWt15000) ; 2 rjmp LcdWt ; 4 ; ; Verzoegerung 4,1 ms ; .EQU cLcdWt4100 = (8*4100-13)/4 ; = 8196 LcdWt4100: ldi ZH,HIGH(cLcdWt4100) ; 1 ldi ZL,LOW(cLcdWt4100) rjmp LcdWt ; ; Verzoegerung 4,5 ms ; .EQU cLcdWt4500 = (4500*8-13)/4 LcdWt4500: ldi ZH,HIGH(cLcdWt4500) ; 1 ldi ZL,LOW(cLcdWt4500) ; 2 rjmp LcdWt ; 4 ; ; Verzoegerung 1,64 ms ; .EQU cLcdWt1640 = (1640*8-13)/4 ; = 3276 LcdWt1640: ldi ZH,HIGH(cLcdWt1640) ; 1 ldi ZL,LOW(cLcdWt1640) ; 2 rjmp LcdWt ; 4 ; ; Verzegerung 100 µs ; .EQU cLcdWt100 = (100*8-13)/4 LcdWt100: ldi ZH,HIGH(cLcdWt100) ldi ZL,LOW(cLcdWt100) rjmp LcdWt ; ; Verzoegerung 40 µs ; .EQU cLcdWt40 = (40*8-13)/4 ; = 76 LcdWt40: ldi ZH,HIGH(cLcdWt40) ; 1 ldi ZL,LOW(cLcdWt40) ; 2 nop ; 3 nop ; 4 ; ; Wartet auf Z Verzoegerung ; Anzahl Takte einschlieszlich ret = 4*(Z-1)+7 ; Verzoegerung in µs bei 8 MHz: (4*(Z-1)+7)/8 ; LcdWt: sbiw ZL,1 ; 2 brne LcdWt ; 2/1 ret ; 4 ; ; Verzoegerung fuer einen aktiven E-Puls ist 1 µs ; LcdDel1: nop ret ; ; Aktiviere E fuer 1 µs ; LcdE: sbi pLcdCO,bLcdE ; setze E aktiv rcall LcdDel1 ; 1 µs Verzoegerung cbi pLcdCO,bLcdE ; loesche E ret ; ; Pruefe ob die LCD busy ist nach Ausgabe eines Zeichens ; stellt zu Beginn fest, ob die LCD angeschlossen ist ; LcdChck: cbi pLcdCO,bLcdRw ; Schreibe Daten an LCD sbi pLcdCO,bLcdRs ; setze RS-Eingang aktiv clr rmp ; alle Datenbits auf Eingang out pLcdDD,rmp ser rmp ; Pullup-Widerstaende einschalten out pLcdDO,rmp cbi pLcdCO,bLcdRs ; loesche Rs sbi pLcdCO,bLcdRw ; setze RW sbi pLcdCO,bLcdE ; activiere E in rmp,pLcdDI ; lese Display tst rmp ; springe wenn Adresse und Busy nicht Null sind sbr rFlg,1<2, setzt Zeile 4 rjmp LcdLine4 LcdLine1: clr rmp ; Zeile 1 startet bei 0 rjmp LcdLine4 LcdLine2: ldi rmp,0x40 ; Zeile 2 startet bei 0x40 rjmp LcdLine4 LcdLine3: ldi rmp,20 ; Zeile 3 startet bei 20 LcdLine4: sbr rmp,0x80 ; setze Kontrollbit rjmp LcdCtrl ; ; LCD loesche Zeile ; LcdLineCl: mov ZH,rmp ; sichere Zeilennummer rcall LcdLine ; setze Zeile ldi rmp,' ' ; Leerzeichen mov R0,rmp ; nach R0 ldi ZL,20 ; ZL ist Zaehler LcdLineCl1: rcall LcdR0 ; schreibe Zeichen in R0 dec ZL ; naechstes brne LcdLineCl1 ; noch mal mov rmp,ZH ; stelle rmp wieder her rjmp LcdLine ; ; LcdPos setzt die LCD auf die Position in Z ; LcdPos: cpi ZH,1 ; Zeile = 0 oder 1 brcs LcdPos1 ; ZH=0, setzt Zeile 1 breq LcdPos2 ; ZH=1, setzt Zeile 2 cpi ZH,2 breq LcdPos3 ; ZH=2, setzt Zeile 3 ldi rmp,0x54 ; ZH>2, setzt Zeile 4 rjmp LcdPos4 LcdPos1: clr rmp ; Zeile 1 startet bei 0 rjmp LcdPos4 LcdPos2: ldi rmp,0x40 ; Zeile 2 startet bei 0x40 rjmp LcdPos4 LcdPos3: ldi rmp,20 ; Zeile 3 startet bei 20 LcdPos4: add rmp,ZL ; addiere Position in Zeile sbr rmp,0x80 rjmp LcdCtrl ; ; Setzt die LCD Cursor Position ; LcdCursor: sbrs rFlg,bLcdOk ; LCD ok? ret lds rmp,sLcdCs ; lese Cursor-Position cpi rmp,8 ; mindest-Position brcc LcdCursor1 rcall KeyMenueFirst ; Zeige Menue in Zeile an LcdCursor1: ldi ZH,3 ; Zeile 4 lds ZL,sLcdCs ; Lese erneut Position rjmp LcdPos ; ; LCDHEX2 schreibt den Inhalt von rmp in Hex (debug) ; LcdHex2: push rmp swap rmp rcall LcdHexN pop rmp LcdHexN: andi rmp,0x0F cpi rmp,0x0A brcs LcdHexN1 subi rmp,-7 LcdHexN1: subi rmp,-'0' rcall LcdChar ret ; ; LcdDecDigit zieht die Dezimalzahl ab und schreibt eine Ziffer ; LcdDecDigit: clr rmp ; zaehlt waehrend der Subtraktion LcdDecDigit1: cp R2,ZL ; vergleiche LSB cpc R3,ZH ; dto., MSB brcs LcdDecDigit2 ; Subtraktion beendet sub R2,ZL ; subtrahiere LSB sbc R3,ZH ; dto., MSB inc rmp ; erhoehe Anzahl der Subtraktionen rjmp LcdDecDigit1 ; weiter LcdDecDigit2: tst rmp ; null mal? brne LcdDecDigit3 ; nein tst R0 ; pruefe of fuehrende Nullen aktiv brne LcdDecDigit3 ldi rmp,' ' ; fuehrende Null loeschen rcall LcdChar ; Leerzeichen ausgeben clr R0 ret LcdDecDigit3: subi rmp,-'0' ; addiere ASCII-Null rcall LcdChar ; stelle Ziffer im LCD dar clr R0 ; keine fuehrende Nullen mehr inc R0 ret ; ; LcdDec schreibt die Zahl R3:R2 in Dezimal auf das Display ; 5, 4, 3 or 2 Ziffern werden dargestellt ; LcdDec5: clr R0 ; fuehrende Nullen unterdruecken ldi ZH,HIGH(10000) ldi ZL,LOW(10000) rcall LcdDecDigit LcdDec4: ldi ZH,HIGH(1000) ldi ZL,LOW(1000) rcall LcdDecDigit LcdDec3: ldi ZH,HIGH(100) ldi ZL,LOW(100) rcall LcdDecDigit LcdDec2: clr ZH ldi ZL,10 rcall LcdDecDigit ldi rmp,'0' add rmp,R2 rjmp LcdChar ; ; Ende der LCD-Routinen ; ; Lcd texte ; ; Init Text auf Display ; LcdTxtInit1: .DB " Akkulader V1.0 ",0 LcdTxtInit2: .DB "(C)2005 by DG4FAC",0 LcdTxtInit3: .DB "Vier Kanal Akku- ",0 LcdTxtInit4: .DB " lader Prozessor ",0 ; ; Ende der LCD Include-Datei ;