Code:
.nolist
.include "m16def.inc"
.list
.def data = r0
.def flag = r10
.def temp = r16
.def tim1 = r17
.def tim2 = r18
.def addr = r20
.def tmp1 = r19
.def blinkr = r21
.def cnt = r22
.def bin = r23
.def lowb = r24
.def highb = r25
.equ RS = 4 ;alle von PortC
.equ RW = 5
.equ E = 6
.equ Minus = 0
.cseg
initial:
cbi PortD, 7 ;Hintergrundbeleuchtung ausschalten
ldi temp, low(ramend)
out SPL, temp
ldi temp, high(ramend)
out SPH, temp ;Stackpointer initialisiert
ldi temp, 0b10000000 ;MSB setzen (JTD)
out MCUCSR, temp
out MCUCSR, temp ;2x -> kein JTAG
;I/O-Ports definieren
ldi temp, 0b11000000
out DDRD, temp ;Port D: Pin7,6->A, Rest->E
ldi temp, 0b00000001
out DDRB, temp ;Port B: Pin1->Ausgang, Rest->Eingang
ldi temp, 0xFF
out DDRC, temp ;Port C -> Ausgang
;A/D-Wandler initialisieren
sbi ADCSR, 7 ;anschalten
in temp, ADCSR
sbr temp, 0b00100111 ;Vorteiler=128; ADC an, Autotrigger
out ADCSR, temp ;uebernehmen
ldi temp, 0b11000001 ;V(ref) = 2,56V; kanal1
out ADMUX, temp
sbi ADCSR, 6 ;und los
LCDinit: cli
call wait500ms
call wait500ms
ldi temp, 0b11
out PortC, temp
call enable ;erstesmal uebernehmen
call wait5ms
call enable ;2.mal uebernehmen
call wait5ms
call enable ;3.mal uebernehmen
call wait5ms
ldi temp, 0b00000010 ;4-bit Modus einstellen
call SendCom
ldi temp, 0b00101000 ;Zeilenzahl und Matrix setzen
call SendCom
ldi temp, 0b00001000 ;Display abschalten
call SendCom
ldi temp, 0b00000001 ;Display loeschen
call SendCom
ldi temp, 0b00000110 ;Eingabemodus setzen
call SendCom
ldi temp, 0b00001100 ;Display einschalten
call SendCom ; ohne Cursor und ohne blinken
sei
ldi ZL, low(text1)
ldi ZH, high(text1)
call SendTxt
ldi temp, 0b11000011
call SendCom
ldi ZL, low(GradC)
ldi ZH, high(GradC)
call SendTxt
ldi temp, 0b11001110
call SendCom
ldi ZL, low(GradC)
ldi ZH, high(GradC)
call SendTxt
sbi PortD, 7 ;Hintergrundbeleuchtung einschalten
endlos: call wait5ms
in lowb, ADCL ;Lowbyte der Umwandlung einlesen
in highb, ADCH ;Highbyte einlesen
push lowb
push highb ;fuer spaeter
ldi temp, 0b11000000
call SendCom
call umrech
ldi temp, 0b0 ;
call chngchnl ;2.Kanal (Kanal1) auswaehlen
call wait5ms ;Zeit fuer neue Umwandlungen lassen
in lowb, ADCL ;Lowbyte der Umwandlung einlesen
in highb, ADCH ;Highbyte einlesen
ldi temp, 0b11001011
call SendCom
call umrech
ldi temp, 0b1
call chngchnl
cbi PortB, 0
sbrc flag, Minus ;IP+2 bei gesetztem "Minus"-flag
sbi PortB, 0
jmp endlos ;von vorn
;---Prozeduren fuer die verschiedenen Zeitspannen---
wait5ms: cli
push temp
ldi temp, 78
out OCR0, temp ;OutputCompareRegister=10000
ldi temp, 0b101
out TCCR0, temp ;8bit-Timer mit Vorteiler=8 starten
warten: in temp, TIFR
sbrs temp, 1 ;Flag testen (TCNT0=OCR0)
jmp warten
sbr temp, 0b10
out TIFR, temp ;Flag zuruecksetzen
eor temp, temp ;temp=0
out TCCR0, temp
out TCNT0, temp ;=0
pop temp
sei
ret
wait500ms: cli
push tmp1
ldi tmp1, 100
wait500msa: call wait5ms
dec tmp1
brne wait500msa
pop tmp1
sei
ret ;100 mal 5ms
;___________einen "Enable"-Impuls starten (Display uebernimmt Daten)_____________________
enable: sbi PortC, E ;Enable-Pin -> H
call wait5ms ;5000ns spaeter
cbi PortC, E ;Enable-Pin -> L
ret
;___________Einen String ans Display senden_____________________________________________
SendTxt: push temp
push cnt
cli
clr cnt
lsl ZL
rol ZH ;Z-Pointer mal 2
SendTxta: lpm ;Byte von Adresse (Z) im Flash laden
mov temp, data ;in data (r0) landete das byte
cpi temp, 0
breq SendTxtb
call SendDat ;an LCD senden
adiw ZH:ZL, 1 ;Z-Pointer incrementieren
inc cnt
jmp SendTxta
SendTxtb: ldi temp, 0x20
call SendDat
inc cnt
cpi cnt, 16
brlo SendTxtb
ldi temp, 0b10000000
call SendCom
sei
pop cnt
pop temp
ret
;___________Prozedur zum Senden von Befehlen ans Display (4bit-Modus)___________________
SendCom: cli
push tmp1
push temp
mov tmp1, temp
swap temp ;hoeherwertiges Nibble->niederwertiges
andi temp, 0x0F ;hoeherwertiges->loeschen (auf 0 setzen)
out PortC, temp
call enable ;Uebernehemen
andi tmp1, 0x0F
out PortC, tmp1
call enable
call wait5ms
pop temp
pop tmp1
sei
ret
;___________Prozedur zum senden von Zeichen an das Display (4bit-Modus)_________________
SendDat: cli
push tmp1
push temp
mov tmp1, temp
swap temp ;hoeherwertiges Nibble->niederwertiges
andi temp, 0x0F ;hoeherwertiges->loeschen (auf 0 setzen)
out PortC, temp
sbi PortC, RS
call enable ;Uebernehemen
andi tmp1, 0x0F
out PortC, tmp1
sbi PortC, RS
call enable
call wait5ms
pop temp
pop tmp1
sei
ret
;---Prozedur zum Umrechnen des 10bit A/D-ergebnisses in eine Temperatur---
umrech: push lowb
push highb ;fuer spaeter
ldi temp, 88 ;mit 88 multiplizieren
ldi tmp1, 0
mul lowb, temp ;multiplizieren
mov tim1, r0
mov tim2, r1
mul highb, temp
add r0, tim2 ;hoeheres mit niedrigem addieren
adc r1, tmp1 ;falls Ueberlauf
mov lowb, r0
mov highb, r1
subi lowb, 0x18
mov bin, lowb
pop highb
pop lowb ;wiederherstellen
;cpi highb, 0x03
;brne umrech_e ;wenn nicht gleich -> umrech_e
cpi lowb, 0x2F
brlo umrech_k ;wenn kleiner 0°C springen
mov temp, flag
cbr temp, 0b1
mov flag, temp ;"Minusflag" loeschen
jmp umrech_e ;sonst beenden
umrech_k: ldi tmp1, 0xFF
sub tmp1, bin
inc tmp1 ;minusgrade ausrechnen
mov bin, tmp1
mov temp, flag
sbr temp, 0b1
mov flag, temp ;"Minusflag" setzen
umrech_e: ldi tmp1, '0' ;Ascii von 0
ldi cnt, 0 ;counter = 0
ldi tim1, 3 ;HilfCouNTer = 3
ldi XL, 0x60
ldi XH, 0 ;Adresse von 1. Speicherstelle im SRAM setzen
umrech_c: cpi bin, 10 ;Rest mit 10 vergleichen
brlo umrech_a ;wenn kleiner Schleife verlassen
subi bin, 10 ;10 abziehen
inc cnt ;incrementieren
jmp umrech_c
umrech_a: add bin, tmp1 ;-> Ascii-Code
st X+, bin ;Bin (Ascii-Code) in SRAM ($60) speichern und X-Pointer incrementieren
mov bin, cnt ;Ergebnis der Division nach, bin
clr cnt
dec tim1
breq umrech_b ;wenn 3mal durchgelaufen, dann beenden
jmp umrech_c
umrech_b: ;sbiw XL, 1 ;3. Ascii-Code laden (entspricht "Hunderter")
ld temp,-X
ldi temp, '+' ;positive Temperatur anzeigen
sbrc flag, 0
ldi temp, '-' ;negative Temperatur anzeigen
call SendDat
ld temp,-X ;2. Ascii-Code laden (entspricht "Zehner")
call SendDat
ld temp,-X ;1. Ascii-Code laden (entspricht "Einer")
call SendDat
ret
chngchnl: cli ADCSR, 5 ;anhalten
in tmp1, ADMUX
andi tmp1, 0b11100000 ;unterste 5 bit loeschen
or tmp1, temp ;entsprechende bits setzen
out ADMUX, tmp1
sbi ADCSR, 5
sbi ADCSR, 6 ;wieder starten
ret
;---Strings zum Ausgeben auf dem Display (0-terminiert)---
text1: .db "aktuelle Messung",0
kanal0: .db "0:",0
kanal1: .db "1:", 0
GradC: .db 0b11011111,"C",0
Ich vermute der Fehler liegt in dem Unterprogramm "umrech", welches den Wert vom ADC in eine Temperatur umrechnet und am Display ausgibt.
Lesezeichen