Bei mir funzt es immer noch nicht, deshalb hier den Code direkt
:.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