.include "m8def.inc" .def temp1 = r16 .def temp2 = r17 .def temp3 = r18 .MACRO locate ;(Zeile,Spalte) push temp1 ldi temp1, 0b10000000|(((@0)-1)<<6)|((@1)-1) rcall lcd_command pop temp1 .ENDMACRO .org 0x000 rjmp init reti reti reti reti reti reti reti reti reti reti reti reti reti rjmp adccomp reti reti reti reti init: ldi temp1, LOW(RAMEND) ;Stackpointer initialisieren out SPL, temp1 ldi temp1, HIGH(RAMEND) out SPH, temp1 ldi temp1, 0xFF ;Port B = Ausgang out DDRB, temp1 ;******************************************************************************** ldi temp1, 0b01000000 out ADMUX, temp1 ldi temp1, 0b10001111 out ADCSR, temp1 sei rcall lcd_init ;Display initialisieren rcall lcd_clear ;Display löschen sbi ADCSR, 6 loop: rjmp loop ;A/D-Wandlung fertig adccomp: ldi R30, ADCL ldi R31, ADCH ldi r22, -1 + '0' _bcd7: inc r22 subi r30, low(1000) ;-1000 sbci r31, high(1000) brcc _bcd7 ldi r21, 10 + '0' _bcd8: dec r21 subi r30, low(-100) ;+100 sbci r31, high(-100) brcs _bcd8 ldi r20, -1 + '0' _bcd9: inc r20 subi r30, 10 ;-10 brcc _bcd9 subi r30, -10 - '0' mov r19, r30 rcall lcd_clear locate 1,4 mov temp1, R19 rcall lcd_data locate 1,3 mov temp1,R20 rcall lcd_data locate 1,2 mov temp1, R21 rcall lcd_data locate 1,1 mov temp1, R22 rcall lcd_data sbi ADCSR, 6 ret ;sendet ein Datenbyte an das LCD lcd_data: mov temp2, temp1 ;"Sicherungskopie" für ;die Übertragung des 2.Nibbles swap temp1 ;Vertauschen andi temp1, 0b00001111 ;oberes Nibble auf Null setzen sbr temp1, 1<<4 ;entspricht 0b00010000 out PORTB, temp1 ;ausgeben rcall lcd_enable ;Enable-Routine aufrufen ;2. Nibble, kein swap da es schon ;an der richtigen stelle ist andi temp2, 0b00001111 ;obere Hälfte auf Null setzen sbr temp2, 1<<4 ;entspricht 0b00010000 out PORTB, temp2 ;ausgeben rcall lcd_enable ;Enable-Routine aufrufen rcall delay50us ;Delay-Routine aufrufen ret ;zurück zum Hauptprogramm ;sendet einen Befehl an das LCD lcd_command: ;wie lcd_data, nur ohne RS zu setzen mov temp2, temp1 swap temp1 andi temp1, 0b00001111 out PORTB, temp1 rcall lcd_enable andi temp2, 0b00001111 out PORTB, temp2 rcall lcd_enable rcall delay50us ret ;erzeugt den Enable-Puls lcd_enable: sbi PORTB, 5 ;Enable high nop ;3 Taktzyklen warten nop nop cbi PORTB, 5 ;Enable wieder low ret ;Und wieder zurück ;Pause nach jeder Übertragung delay50us: ;50us Pause ldi temp1, $42 delay50us_:dec temp1 brne delay50us_ ret ;wieder zurück ;lange Pause für entrprellen delay25ms: rcall delay5ms rcall delay5ms rcall delay5ms rcall delay5ms rcall delay5ms ret ;Längere Pause für manche Befehle delay5ms: ;5ms Pause ldi temp1, $21 WGLOOP0: ldi temp2, $C9 WGLOOP1: dec temp2 brne WGLOOP1 dec temp1 brne WGLOOP0 ret ;wieder zurück ;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden lcd_init: ldi temp3,50 powerupwait: rcall delay5ms dec temp3 brne powerupwait ldi temp1, 0b00000011 ;muss 3mal hintereinander gesendet out PORTB, temp1 ;werden zur Initialisierung rcall lcd_enable ;1 rcall delay5ms rcall lcd_enable ;2 rcall delay5ms rcall lcd_enable ;und 3! rcall delay5ms ldi temp1, 0b00000010 ;4bit-Modus einstellen out PORTB, temp1 rcall lcd_enable rcall delay5ms ldi temp1, 0b00101000 ;noch was einstellen... rcall lcd_command ldi temp1, 0b00001100 ;...nochwas... rcall lcd_command ldi temp1, 0b00000100 ;endlich fertig rcall lcd_command ret ;Sendet den Befehl zur Löschung des Displays lcd_clear: ldi temp1, 0b00000001 ;Display löschen rcall lcd_command rcall delay5ms ret ; print: sendet die durch den Z-Pointer adressierte Zeichenkette 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 temp1, r0 ; Inhalt von R0 nach R16 kopieren rcall lcd_data ; an LCD senden adiw ZL, 1 ; Adresse des Z-Pointers um 1 erhöhen rjmp print ; wieder zum Anfang springen print_end: ret