;****************************************************** ;Test fuer LCD userdefinierte Charakters ;MCU Attiny4313 (resp. 2313); ;MCU Frequenz STK500-Board (unkritisch bis ca.4 MHz) ;LCD 2x16; HD44780 compatible ;RS=PB4; Enable=PB5; R/Wquer=GND ; PortB LCD Ausgabe: R/W=GND ; PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 ; n/a LED ena rs D7 D6 D5 D4 ; Adapter auf LCD-Port: ; PB7 PB6 PB5 PB4 PB3 PB2 PB1 PB0 ; D7 D6 D5 D4 LED n/a ena rs ; ATtiny4313 memory use summary [bytes]: ; Segment Begin End Code Data Used Size Use% ;-------------------------------------------------- ;[.cseg] 0x000000 0x0002b8 616 80 696 4096 17.0% ;[.dseg] 0x000060 0x000060 0 0 0 256 0.0% ;[.eseg] 0x000000 0x000000 0 0 0 256 0.0% ;Assembly complete, 0 errors. 0 warnings ;-------------------------------------------------- ; Rev.:02042018 ;****************************************************** ; .nolist .include "tn4313def.inc";"2313def.inc" .list ; .def temp = r16 ; Temporaerregister 1 .def temp1 = r17 ; Temporaerregister 2 .def temp2 = r18 ; Temporaerregister 3 .def temp3 = r19 ; Temporaerregister 4 .def zeit = r20 ; reserviert .def zeit2 = r22 .equ daten = portb ; Synonyme Portbezeichnungen .equ impuls = portb ; fuer RS und Enable Pinout PORTB .equ licht = portb ; fuer LED-Backlight .equ rs = 4 ; Portbit fuer RS festlegen .equ ena = 5 ; Portbit fuer Enable festlegen .equ lit = 6 ; Bit LED Hintergrundbeleuchtung .equ zeit0 = 500 ; Konstanten fuer Delay .equ zeit1 = 65535 ; ; .cseg ; Codesegment .org 0x0000 ; Anfangsadresse bei Null ; rjmp hauptprogramm ; hauptprogramm: ldi temp, low(RAMEND) ; Stack initialisieren out SPL, temp ldi temp, high(RAMEND) ; nur bei AVR-MCUs mit out SPH, temp ; hoeherem Speicher als ATTiny2313 ser temp out DDRB, temp ; Port B Ausgang fuer LCD out portb, temp ; Pullups rcall wait3 ; LCD POSR rcall lcd_routine sbi licht, lit ; Hintergrundbeleuchtung einschalten rcall text ; Ausgabe normaler Chars rcall ascii_00 ; Chars zuordnen und Pixel setzen rcall ascii_01 rcall ascii_02 rcall ascii_03 rcall ascii_04 rcall ascii_05 rcall ascii_06 rcall ascii_07 rcall ausg rcall ende ; ausg: ; Ausgabe userdefinierter Chars ldi temp, 0xC0 ; Position Anfang Zeile 2 rcall cmd2lcd ldi temp, 0x00 ; Zeichen ASCII_00 rcall char2lcd ldi temp, 0xC2 ; Position Spalte 3, Zeile 2 rcall cmd2lcd ldi temp, 0x01 ; Zeichen ASCII_01 rcall char2lcd ldi temp, 0xC4 ; Position Spalte 5, Zeile 2 rcall cmd2lcd ldi temp, 0x02 ; Zeichen ASCII_02 rcall char2lcd ldi temp, 0xC6 ; Position Spalte 7, Zeile 2 rcall cmd2lcd ldi temp, 0x03 ; Zeichen ASCII_03 rcall char2lcd ldi temp, 0xC8 ; Position Spalte 9, Zeile 2 rcall cmd2lcd ldi temp, 0x04 ; Zeichen ASCII_04 rcall char2lcd ldi temp, 0xCA ; Position Spalte 11,Zeile 2 rcall cmd2lcd ldi temp, 0x05 ; Zeichen ASCII_05 rcall char2lcd ldi temp, 0xCC ; Position Spalte 13,Zeile 2 rcall cmd2lcd ldi temp, 0x06 ; Zeichen ASCII_06 rcall char2lcd ldi temp, 0xCE ; Position Spalte 15,Zeile 2 rcall cmd2lcd ldi temp, 0x07 ; Zeichen ASCII_07 rcall char2lcd ret ; ende: ; Programmende-Schleife cbi licht, lit ; Flackerlicht rcall wait3 ; Hintergrundbeleuchtung sbi licht, lit rcall wait3 ; ; hier evtl. in neue Charsdef. rein ; ; soviel, wie Speicher hergibt. rjmp ende ; text: ; Festtext: "Neue Charakters" ldi temp, 0x80 ; Positionierung Anfang rcall cmd2lcd ; Zeile 1, Spalte 1 rcall wait1 ldi ZL, LOW(text1*2) ; Adresse des Strings in den ldi ZH, HIGH(text1*2) ; Z-Pointer laden rcall print ; Funktion print aufrufen rcall wait2 ret ; print: lpm ; erstes Byte des Strings nach R0 lesen tst R0 ; R0 auf 0 testen breq print_end ; wenn 0, dann zu print_end mov temp, r0 ; Inhalt von R0 nach temp kopieren rcall ausgabe adiw ZL:ZH, 1 ; Adresse des Z-Pointers um 1 erhoehen rjmp print ; zum Anfang springen, um naechstes ; ; Byte aus dem cseg-Label text1;zu holen print_end: rcall wait2 ret ; ausgabe: rcall char2lcd ret ; ascii_00: ; Charakters zuordnen ldi temp, 0x40 ; und Pixel definieren rcall cmd2lcd ; "Set CGRAM address"-Steuerbefehl rcall wait1 ; fuer ASCII-Code hex 00 ldi ZL, LOW(ascii_0*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_0*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_01: ldi temp, 0x48 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 01 rcall wait1 ldi ZL, LOW(ascii_1*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_1*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_02: ldi temp, 0x50 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 02 rcall wait1 ldi ZL, LOW(ascii_2*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_2*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_03: ldi temp, 0x58 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 03 rcall wait1 ldi ZL, LOW(ascii_3*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_3*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_04: ldi temp, 0x60 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; ASCII-Code hex 04 rcall wait1 ldi ZL, LOW(ascii_4*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_4*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_05: ldi temp, 0x68 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 05 rcall wait1 ldi ZL, LOW(ascii_5*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_5*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_06: ldi temp, 0x70 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 06 rcall wait1 ldi ZL, LOW(ascii_6*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_6*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; ascii_07: ldi temp, 0x78 ; "Set CGRAM address"-Steuerbefehl rcall cmd2lcd ; fuer ASCII-Code hex 07 rcall wait1 ldi ZL, LOW(ascii_7*2) ; Adresse des Strings in den ldi ZH, HIGH(ascii_7*2) ; Z-Pointer laden ldi temp2, 0x00 ; Durchlaeufe-Zaehler resetten rcall print_0 ; Funktion print_0 aufrufen rcall wait1 ret ; print_0: ;lpm lpm temp, z+ ; Inhalt des vom Z-Pointer adressierten ; ; 16-Bit-Registers nach temp lesen inc temp2 ; Adresse hinterher 1 rauf cpi temp2, 0x09 ; insgesamt achtmal Pixelwerte holen breq print_end0 ; wenn 9, dann zu print_end0 ;mov temp, r0 ; Inhalt von R0 nach temp kopieren rcall ausgabe ;adiw ZL:ZH, 1 ; Adresse des Z-Pointers um 1 erhoehen rjmp print_0 ; zum Anfang springen, um naechstes ; ; Byte zu holen print_end0: ret ; ;============== Tabellen ================================= ; text1: ; Konstanten des Festtextes .db "Neue Charakters", 0 ; Nullterminierung ; ; ; Tabellen der Charakterpixel ; ; keine Nullterminierung ascii_0: ; Pixel des Charakters ASCII_00 .db 0x1F, 0x15, 0x15, 0x1F, 0x15, 0x15, 0x1F, 0x00 ; ascii_1: ; Pixel des Charakters ASCII_01 .db 0x00, 0x04, 0x04, 0x1F, 0x04, 0x04, 0x00, 0x00 ; ascii_2: ; Pixel des Charakters ASCII_02 .db 0x1F, 0x1B, 0x1B, 0x00, 0x1B, 0x1B, 0x1F, 0x00 ; ascii_3: ; Pixel des Charakters ASCII_03 .db 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x00 ; ascii_4: ; Pixel des Charakters ASCII_04 .db 0x1F, 0x0E, 0x04, 0x15, 0x0A, 0x05, 0x02, 0x01 ; ascii_5: ; Pixel des Charakters ASCII_05 .db 0x06, 0x09, 0x1C, 0x08, 0x1C, 0x09, 0x06, 0x00 ; ascii_6: ; Pixel des Charakters ASCII_06 .db 0x0E, 0x11, 0x1B, 0x15, 0x15, 0x1F, 0x0E, 0x04 ; ascii_7: ; Pixel des Charakters ASCII_07 .db 0x10, 0x08, 0x04, 0x02, 0x01, 0x11, 0x1F, 0x1F ; ;================================================= ; lcd_routine: ; LCD-Initialisierung rcall wait3 push temp ; Sicherung Temporaer- und push temp1 ; Statusregister auf Stack push temp2 clr temp2 in temp2, SREG push temp2 cbi daten, rs ; RS-Bit auf "low" ldi temp, 0x00 ; Reset des Ports out daten, temp rcall enable rcall wait2 ; ; Acht-Bit Init: ; dreimal Hex 0x30 cbi daten, rs ; ldi temp, 0x03 ; out daten, temp ; dazu steht RegisterSelect-Bit rcall enable ; stets auf "low" rcall wait2 ; und jedesmal ein Enable rcall enable ; Impuls togglen rcall wait2 rcall enable rcall wait2 ; ; Acht-zu-Vier-Bit-Modus-Wechsel cbi daten, rs ldi temp, 0x02 ; zunaechst nur 4-Bit-Modus out daten, temp ; untere vier Bit werden rcall enable ; ignoriert, aber immer noch rcall wait2 ; 8-Bit-Bus-Befehlsbreite ; ; Vier-Bit-Modus; zwei Zeilen cbi daten, rs ; dann 4-Bit-Modus ldi temp, 0x28 ; und zweizeilig rcall cmd2lcd ; ab hier bereits Steuerbefehle rcall wait2 ; im Vierbit-cmd2lcd-Modus ; ; senden ; On Off Control; Display einschalten: cbi daten, rs ldi temp, 0x08 ; Displaypuffer ausschalten, rcall cmd2lcd ; Cursor aus, Blinken aus rcall wait2 ; ; Anzeige loeschen: cbi daten, rs ; Anzeige wird im "Space"- ldi temp, 0x01 ; Modus geloescht rcall cmd2lcd ; braucht mehr Zeit rcall wait3 ; ; Entry Mode/Shift Set: cbi daten, rs ldi temp, 0x06 ; Cursor von links nach rechts rcall cmd2lcd ; "increment", kein Schieben rcall wait2 cbi daten, rs ldi temp, 0x10 ; kein Schieben, Cursorbewegung rcall cmd2lcd ; von links nach rechts rcall wait2 cbi daten, rs ldi temp, 0x0C ; Anzeige wieder durchschalten rcall cmd2lcd ; Cursor ein, Blinken ein rcall wait2 cbi daten, rs ldi temp, 0x01 ; Anzeige nochmals loeschen rcall cmd2lcd rcall wait2 pop temp2 ; Temporaerregister und out SREG, temp2 ; Statusregister wiederherstellen pop temp2 pop temp1 pop temp ret ; char2lcd: ; gibt Charakter auf "temp" ueber LCD aus cbi daten,lit ; LCD-Hintergrundbeleuchtung aus push temp ; rettet temps auf Stapel push temp1 mov temp1, temp ; Kopie fuer Nachfolge-Operation andi temp, 0xF0 ; unteres Daten-Nibble ausblenden swap temp ; an Portbelegung anpassen... andi temp, 0x0F ; oberes Portbit-Nibble ausblenden ori temp, 0b00010000 ; RS=high out daten,temp ; Ausgabe D4-D7-Daten-Nibble auf Port D0-D3 rcall enable ; Enableimpuls andi temp1, 0x0F ; oberes Portbit-Nibble ausblenden ori temp1, 0b00010000 ; RS=high out daten,temp1 ; Ausgabe D0-D3-Daten-Nibble auf D0-D3 rcall enable ; Enableimpuls sbi daten,lit ; Hintergrundbeleuchtung ein pop temp1 ; Zurueckholen von temps pop temp rcall wait1 ; Verarbeitungszeit LCD abwarten ret ; cmd2lcd: ; sendet Steuerzeichen auf "temp" an LCD push temp ; rettet "temps" auf Stapel push temp1 mov temp1,temp ; Kopie fuer Nachfolge-Operation andi temp, 0xF0 ; unteres Daten-Nibble ausblenden swap temp ; an Portbelegung anpassen... andi temp, 0x0F ; oberes Portbit-Nibble ausblenden; RS=0 out daten,temp ; Ausgabe D4-D7-Daten-Nibble auf Port D0-D3 rcall enable ; Enableimpuls andi temp1, 0x0F ; oberes Portbit-Nibble ausblenden; RS=0 out daten,temp1 ; Ausgabe D0-D3-Daten-Nibble auf D0-D3 rcall enable ; Enableimpuls senden pop temp1 ; Zurueckholen von temps pop temp rcall wait1 ; Verarbeitungszeit LCD abwarten ret ; enable: ; Enableimpulsgenerierung nop sbi daten, ena ; Enable-Bit auf "high" setzen nop ; Zeitwait1 mindestens nop ; 1000 (500)Nanosekunden laut Datenblatt nop ; lieber ein paar "nops" mehr nop ; spendieren nop nop nop nop nop nop nop nop cbi daten, ena ; Enable-Bit wieder auf "low" zurücksetzen nop ret ; ;- - - - Verzoegerungssschleifen - - - - - - - ; wait1: ; Verzoegerungsschleife 1: push yl ; Register sichern auf Stapel push yh push temp ; Sicherung von Temporaerregistern... push temp1 ; und Statusregister auf Stapel push temp2 in temp2, SREG ; (bei Interrupts notwendig) push temp2 ldi yl, low(zeit0) ; laedt Zaehlregisterpaar ldi yh, high(zeit0) ; mit oben deklariertem Wert... rjmp repeatx ; ..."zeit0" ; wait2: ; Verzoegerungsschleife 2: push yl ; Register sichern auf Stapel push yh push temp ; Sichern von Temporaerregistern push temp1 ; und Statusregister auf Stapel push temp2 in temp2, SREG push temp2 ldi yl, low(zeit1) ; laedt Zaehlregisterpaar ldi yh, high(zeit1) ; mit oben deklariertem Wert... rjmp repeatx ; ..."zeit1" ; wait3: ; Verzoegerungssschleife 3: rcall wait2 nop rcall wait2 nop rcall wait2 nop rcall wait2 nop ret ; repeatx: ; 16-Bit-Subtraktionsschleife: sbiw yl:yh, 1 ; decrementiert Doppelregister brne repeatx ; zaehlt bis Null pop temp2 ; Wiederherstellung out SREG, temp2 ; von "geretteten" Registern etc. pop temp2 pop temp1 pop temp pop yh pop yl ret ; ;***fin***