;LCD-Routinen für Text-Punktmatrix-LCD ;mit Controller 50530. 8 Zeilen je 24 Zeichen ;Seiko C338008 / Samsung 0282A (www.pollin.de Nr: 120141) ;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.hanneslux.de ;============================================================================ ;Folgende Routinen können aufgerufen werden: ;---------------------------------------------------------------------------- ; lcd_init ;initialisiert und löscht den Controller des LCD ;---------------------------------------------------------------------------- ; lcd_data ;Übergibt das Byte (ASCII-Zeichen) im Register "tmp" ;zur Textausgabe. Dabei sind folgende Steuerzeichen ;möglich: ;1: Blinken ausschalten ;2: akt. Ausgabe-Position als Blinkanfang setzen ;3: akt. Ausgabe-Position als Blinkende setzen ;4: Bildschirm löschen ;8: Cursor home (ohne Löschen) ;9: Locate, Position folgt im nächsten Byte ;13: CR, Zeilenwechsel, Rest der Zeile wird gelöscht ;---------------------------------------------------------------------------- ; lcd_out ;gibt ein Zeichen aus dem Ringbuffer an das LCD aus ;Aufruf per Mainloop durch Timer synchronisiert ;---------------------------------------------------------------------------- ; locate Zeile,Spalte ;Macro, setzt Ausgabeposition auf Zeile 0-7 ;und Spalte 0-23 (über Ringbuffer) ;---------------------------------------------------------------------------- ; blink Zeile,Spalte,Anzahl ;Markiert die Blinkposition im VLCD auf ;Zeile (0...7), Spalte (0...23) und Anzahl blinkender ;Zeichen. ;---------------------------------------------------------------------------- ; print Zeichen,Anzahl ;gibt Zeichen (K8) Anzahl (K8) mal aus ;============================================================================ ;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. ;============================================================================ ;Die Ausgabe erfolgt über einen Bildschirmspeicher (vlcd) im SRAM des AVRs. ;Dieser kann linear beschrieben werden, das Entwirren der Zeilenadressen ;erfolgt beim Transfer der Zeichen zum LCD. ;Die Übergabe der Daten erfolgt über das Register "tmp", 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=$f0 ;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 c1port=portc ;Port, an dem I/OC1 angeschlossen ist .equ c1=3 ;Pin, an dem I/OC1 angeschlossen ist ;---------------------------------------------------------------------------- .equ c2port=portc ;Port, an dem I/OC2 angeschlossen ist .equ c2=1 ;Pin, an dem I/OC2 angeschlossen ist ;---------------------------------------------------------------------------- .equ enableport=portc ;Port Anschluss Enable des Controllers. .equ enable=2 ;Pin Anschluss Enable des Controllers. ;============================================================================ ;Im Hauptprogramm müssen folgende Speicherbereiche, Register und Konstanten ;definiert werden: ;Konstanten: clock ;Controllertakt ; zln ;Anzahl Zeilen des LCDs (8) ; spn ;Anzahl Spalten des LCDs (24) ;SRAM: vlcd: .byte zln*spn ;Bildschirmspeicher ; rpos: .byte 1 ;Leseposition VLCD ; wpos: .byte 1 ;Schreibposition VLCD ; blinka: .byte 1 ;Blinkbereich Anfang ; blinke: .byte 1 ;Blinkbereich Ende ;Register: bliz (u) ;Blinkzähler ; tmp (o) ;Datenübergabe, wird nicht gesichert! ; vflags (o) ;Flags für LCD, Bits werden hier definiert ; wh (o) ;working h, temporär, wird gesichert ; zh:zl (o) ;temporär, werden gesichert ;Die eizelnen Bits in 'vflags' werden hier deklariert: .equ zeiwe=0 ;Flag für Zeilenwechsel .equ update=1 ;Flag für Update LCD .equ upsync=2 ;Synchronisationsflag vom Timer-Interrupt .equ loc=3 ;nächstes Zeichen ist Locate-Position ;============================================================================ .macro print ;Zeichen als Byte, Anzahl als Byte (Beides als Konstanten) ;Gibt ein Zeichen mehrfach an LCD aus push wh ldi wh,@1 ;Anzahl als Konstante ldi tmp,@0 ;Das Zeichen als Konstante rcall lcd_data ;an LCD ausgeben dec wh ;Anzahl runter brne pc-2 ;nochmal, wenn nicht 0... pop wh .endmacro ;============================================================================ ; Aufrufbare Routine, initialisiert und löscht das LCD ; Benutzt der Einfachheit halber eine Warteschleife ;---------------------------------------------------------------------------- lcd_init: ;LCD-Initialisierung push zl push zh 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 tmp,' ' ;Leerzeichen lcd_init1: st z+,tmp ;ins VLCD cpi zl,low(vlcd+zln*spn) ;Ende VLCD erreicht? brne lcd_init1 ;nein, nochmal... pop zh pop zl in tmp,lcdport-1 ;Datenrichtung LCD-Datenport holen sbr tmp,lcddatmsk ;benutzte Datenpins als Ausgang out lcdport-1,tmp ;definieren sbi c2port-1,c2 ;I/OC2-Leitung als Ausgang sbi enableport-1,enable ;enable-Leitung als Ausgang sbi c1port-1,c1 ;I/OC1-Leitung als Ausgang rcall wait10ms ldi tmp,0b11011010 ;SF (4-Bit, 5x7) rcall lcd_command ;ausführen rcall wait10ms ldi tmp,0b01010000 ;SE (Cursor++) rcall lcd_command ; rcall wait10ms ; ldi tmp,0b00111100 ;SD (Display ein) (Cursor sichtbar) ldi tmp,0b00110100 ;SD (Display ein) (Cursor aus) rcall lcd_command ; rcall wait10ms ldi tmp,0 ;WS (Disp-Start auf 0) rcall lcd_startadr rcall wait10ms ; ldi tmp,0b00001101 ;SU (keine Unterstreichung) ; rcall lcd_command ; ; Code geht weiter... ;============================================================================ ; Interne Routine, löscht das LCD, gehört zu lcd_init ;---------------------------------------------------------------------------- lcd_clear: ;Sendet den Befehl zum Löschen des Displays ldi tmp,0b00000001 ;CH (Clear-Home) rcall lcd_command ;ausführen ; Code geht weiter... ;============================================================================ ; Interne Routine, wird nur von lcd_init und lcd_clear aufgerufen ;---------------------------------------------------------------------------- wait10ms: ;wartet etwa 10 Millisekunden (per Timer0 synchronisiert) push tmp cbr vflags,1<