;LCD-Routinen für WD-C2704M - Text-Punktmatrix-LCD ;mit 2 Controllern HD44780. 4 Zeilen je 27 Zeichen ;Version mit frei definierbaren Steuerleitungen. ;Diese Routinensammlung baut auf Beispielen von Andreas Schwarz ;und T.S. auf und ist von ...HanneS... zusammengestellt worden. ; hannes.lux@gmx.de / www.hannes.de.md ;============================================================================ ;Diese Sammlung enthält folgende Routinen: ;---------------------------------------------------------------------------- ; lcd_init ;initialisiert und löscht beide Controller des LCD ;---------------------------------------------------------------------------- ; lcd_clear ;löscht das LCD ;---------------------------------------------------------------------------- ; lcd_command ;übergibt das Byte im Register "wl" als Kommando ;an das LCD ;---------------------------------------------------------------------------- ; lcd_data ;übergibt das Byte im Register "wl" zur Textausgabe ;---------------------------------------------------------------------------- ; locate ;Macro zum Einstellen der Ausgabeposition. ;Aufruf: locate Zeile,Spalte ;Zeile: 0-3, Spalte: 0-26 ;============================================================================ ;Die Datei "LCDprint.inc" stellt einige Ausgaberoutinen zur Verfügung, die ;die Ausgabe von Texten und Zahlen erleichtert. Zusammen mit "locate" wird ;die Ausgabe von Menütexten, Zahlen usw. ähnlich einfach wie in BASIC. ;============================================================================ ;Zur Steuerung der LCD-Zugriffe wird ein oberes Register namens "VFLAGS" ;für einige Booleans benötigt. Es muss im Hauptprogramm deklariert werden. ;Die eizelnen Bits werden hier deklariert: .equ zeiwe=1 ;Flag für Zeilenwechsel .equ update=2 ;Flag für Update LCD .equ upsync=3 ;Synchronisationsflag vom Timer-Interrupt .equ neu=4 ;neues Byte eingetroffen .equ empfang=5 ;Flag für Empfangsmodus .equ lcdcontroller1=6 ;Flag für Controller 1 .equ lcdcontroller2=7 ;Flag für Controller 2 ;Die Übergabe der Daten erfolgt über das Register "wl", das im Hauptprogramm ;zu deklarieren ist. Weiterhin muss das Register "wh" deklariert sein. ;============================================================================ ;Anschlussbelegung: ;Die 4 Datenleitungen sollten in einem Nibble liegen. ;Dies kann ein unteres oder oberes Nibble sein. ;Die Auswahl geschieht mit "lcddatmsk" ;Die Steuerleitungen des LCD können über alle ;verfügbaren Ports frei gewählt werden, was diesen ;Treiber sehr flexibel macht. ;---------------------------------------------------------------------------- .equ lcdport=portc ;Port, an dem die 4 Datenleitungen des LCD ;angeschlossen sind. .equ lcddatmsk=$0f ;Maske auf LCD-Datenpins. ;$0f - LCD ist an Bit 0...3 des Ports angeschlossen. ;$f0 - LCD ist an Bit 4...7 des Ports angeschlossen. ;---------------------------------------------------------------------------- .equ rsport=portd ;Port, an dem RS angeschlossen ist .equ rs=5 ;Pin, an dem RS angeschlossen ist ;---------------------------------------------------------------------------- .equ enable1port=portd ;Port Anschluss Enable des ersten Controllers. .equ enable1=6 ;Pin Anschluss Enable des ersten Controllers. ;---------------------------------------------------------------------------- .equ enable2port=portd ;Port Anschluss Enable des zweiten Controllers. .equ enable2=7 ;Pin Anschluss Enable des zweiten Controllers. ;---------------------------------------------------------------------------- .equ rwport=portd ;Port, an dem R/W angeschlossen ist .equ rw=2 ;Pin, an dem R/W angeschlossen ist ;============================================================================ ;============================================================================= ; locate Zeile,Spalte ;Setzt die Ausgabeposition im VLCD auf ;Zeile (0...3) und Spalte (0...26). ;----------------------------------------------------------------------------- .macro locate ;Zeile (0...3), Spalte (0...27) ;Positionierung der Ausgabeposition push wl ;Register sichern ldi wl,((@0 & 3)*spn)+(@1 & 63)+low(vlcd) ;Position im VLCD errechnen sts wpos,wl ;und einstellen pop wl ;Register wiederherstellen .endmacro ;============================================================================= ; blink Zeile,Spalte,Anzahl ;Markiert die Blinkposition im VLCD auf ;Zeile (0...3), Spalte (0...26) und Anzahl blinkender ;Zeichen. ;----------------------------------------------------------------------------- .macro blink ;Zeile (0...3), Spalte (0...27), Anzahl Blinkzeichen ;Positionierung der Blinkposition push wl ;Register sichern ldi wl,((@0 & 3)*spn)+(@1 & 63)+low(vlcd) ;Startposition im VLCD errechnen sts blinka,wl ;und einstellen subi wl,-@2 ;Endposition im VLCD sts blinke,wl ;einstellen pop wl ;Register wiederherstellen .endmacro ;============================================================================ ; Aufrufbare Routine, initialisiert und löscht das LCD ;---------------------------------------------------------------------------- lcd_init: ;LCD-Initialisierung ldi zl,low(vlcd) ;Z-Pointer ldi zh,high(vlcd) ;auf VLCD sts rpos,zl ;VLCD auf Anfang des sts wpos,zl ;Bildschirmspeichers setzen sts blinka,zl ;Blinkpointer sts blinke,zl ;auch ldi wl,' ' ;Leerzeichen lcd_init1: st z+,wl ;ins VLCD cpi zl,low(vlcd+zln*spn) ;Ende VLCD erreicht? brne lcd_init1 ;nein, nochmal... ; ret ;Debug... sbr vflags,(1<15ms warten, nachdem Vcc > 4,5V ist ldi xl,20 ;>15ms warten, nachdem Vcc > 4,5V ist powerupwait: ;hier 250ms warten, dafür keine Spannungsprüfung rcall delay5ms dec xl brne powerupwait pop xl ;alten Inhalt zurück holen cbi rwport,rw ;Steuerleitungen auf cbi rsport,rs ;L-Pegel legen ;Startsequenz in wl,lcdport ;ganzen Port einlesen cbr wl,lcddatmsk ;Platz für Datenbits löschen ldi wh,0b00110011 ;benötigte Datenbits in beide Nibbles andi wh,lcddatmsk ;nur das genutzte Nibble or wl,wh ;übernehmen out lcdport,wl ;und wieder ausgeben ;dreimal ausgeben rcall lcd_impuls ;1. Ausgabe (von 3) rcall delay5ms ;>4,1ms warten rcall lcd_impuls ;2 rcall delay5ms ;>0,1ms warten rcall lcd_impuls ;und 3! rcall delay5ms ;Ab hier BUSY prüfen ;4-Bit-Modus aktivieren in wl,lcdport ;ganzen Port einlesen cbr wl,lcddatmsk ;Platz für Datenbits löschen ldi wh,0b00100010 ;benötigte Datenbits in beide Nibbles andi wh,lcddatmsk ;nur das genutzte Nibble or wl,wh ;übernehmen out lcdport,wl ;und wieder ausgeben rcall lcd_impuls rcall delay5ms ;ab jetzt 4-Bit-Zugriff mit Busy-Abfrage ldi wl,0b00101000 ;4bit-Modus einstellen rcall lcd_command rcall delay5ms ldi wl,0b00001100 ;Display ein, Cursor aus rcall lcd_command rcall delay5ms ldi wl,0b00000100 ;Entry-Mode rcall lcd_command rcall delay5ms ;(Code geht weiter...) ;============================================================================ ; Aufrufbare Routine, löscht das LCD ;---------------------------------------------------------------------------- lcd_clear: ;Sendet den Befehl zur Löschung des Displays sbr vflags,(1<