PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : werte als spannung ausgeben



sahra
08.11.2010, 16:45
kann mir bitte jemand sagen wo der Fehler ist,
danke


;//////////////////////////////////////////////////////////////////////////
;Titel: UART.asm
;
;
;//////////////////////////////////////////////////////////////////////////

.include "m88def.inc"

.def z0 = r1 ; Zahl für Integer -> ASCII Umwandlung
.def z1 = r2
.def z2 = r3
.def z3 = r4
.def temp1 = r16 ; allgemeines Register, zur kurzfristigen Verwendung
.def temp2 = r17 ; Register für 24 Bit Addition, niederwertigstes Byte (LSB)
.def temp3 = r18 ; Register für 24 Bit Addition, mittlerers Byte
.def temp4 = r19 ; Register für 24 Bit Addition, höchstwertigstes Byte (MSB)
.def adlow = r20 ; Ergebnis vom ADC-Mittelwert der 256 Messungen
.def adhigh = r21 ; Ergebnis vom ADC-Mittelwert der 256 Messungen
.def zeichen = r23 ; Zeichen zur Ausgabe auf den UART
.def temp5 = r24
.def temp6 = r25






;::::::::::::::::::::::::::::::::::::::::::::::::: ::::::::::::::::::::::::::::::::::::
;Baud Rate berechnen
;-------------------
.equ Faktor = 4883
.equ F_CPU = 3686400 ; Systemtakt in Hz
.equ BAUD = 9600 ; Baudrate

; Berechnungen
.equ UBRR_VAL = ((F_CPU+BAUD*8)/(BAUD*16)-1) ; clever runden
.equ BAUD_REAL = (F_CPU/(16*(UBRR_VAL+1))) ; Reale Baudrate
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000) ; Fehler in Promille

.if ((BAUD_ERROR>10) || (BAUD_ERROR<-10)) ; max. +/-10 Promille Fehler
.error "Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!"
.endif

; RAM
.dseg
.org 0x60
Puffer: .byte 10


; hier geht das Programm los
.cseg
.org 0

;************************************************* **************************
;UART Initalisieren************************************* ********************
;************************************************* **************************

; Stackpointer initialisieren

ldi temp1, HIGH(RAMEND)
out SPH, temp1
ldi temp1, LOW(RAMEND)
out SPL, temp1

ldi temp1, 0x0F
out DDRB, temp1

uart_init:

ldi temp1, LOW(UBRR_VAL) ; Baudrate einstellen
sts UBRR0L, temp1
ldi temp1, HIGH(UBRR_VAL)
sts UBRR0H, temp1

ldi temp1, (1<<UMSEL01 | 3<<UCSZ00) ;Frame-Format: 8 bit
sts UCSR0C, temp1

ldi temp1, (1<<TXEN0);| (1<<RXEN0) ;Empfangen und Senden erlauben
sts UCSR0B, temp1

main:
ldi temp1, low(5600)
ldi temp2, high(5600)

mov adlow, temp1
mov adhigh, temp2

ldi temp5,low(4883)
ldi temp6,high(4883)
rcall mul_16x16

ldi XL, low(Puffer)
ldi XH, high(Puffer)
rcall Int_to_ASCII

;an UART Senden

ldi ZL, low(Puffer+3)
ldi ZH, high(Puffer+3)
ldi temp1, 1
rcall sende_zeichen ; eine Vorkommastelle ausgeben

ldi zeichen, ',' ; Komma ausgeben
rcall sende_einzelzeichen

ldi temp1, 3 ; Drei Nachkommastellen ausgeben
rcall sende_zeichen

ldi zeichen, 'V' ; Volt Zeichen ausgeben
rcall sende_einzelzeichen

ldi zeichen, 10 ; New Line Steuerzeichen
rcall sende_einzelzeichen

ldi zeichen, 13 ; Carrige Return Steuerzeichen
rcall sende_einzelzeichen






rjmp main



;in ASCII umwandeln
; Division durch mehrfache Subtraktion
; 32 Bit Zahl in ASCII umwandeln
; geschwindigkeitsoptimierte Version
; Zahl liegt in temp1..4
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird
; Adressierung über X Pointer

Int_to_ASCII:

push ZL ; Register sichern
push ZH
push temp5
push temp6

ldi ZL,low(Tabelle*2) ; Zeiger auf Tabelle
ldi ZH,high(Tabelle*2)
ldi temp5, 10 ; Schleifenzähler

Int_to_ASCII_schleife:
ldi temp6, -1+'0' ; Ziffernzähler zählt direkt im ASCII Code
lpm z0,Z+ ; Nächste Zahl laden
lpm z1,Z+
lpm z2,Z+
lpm z3,Z+

Int_to_ASCII_ziffer:
inc temp6 ; Ziffer erhöhen
sub temp1, z0 ; Zahl subrahieren
sbc temp2, z1 ; 32 Bit
sbc temp3, z2
sbc temp4, z3
brge Int_to_ASCII_ziffer ; noch kein Unterlauf, nochmal

add temp1, z0 ; Unterlauf, eimal wieder addieren
adc temp2, z1 ; 32 Bit
adc temp3, z2
adc temp4, z3
st X+,temp6 ; Ziffer speichern
dec temp5
brne Int_to_ASCII_schleife ; noch eine Ziffer?

pop temp6
pop temp5
pop ZH
pop ZL ; Register wieder herstellen
ret





;Warteschleife bis wieder ein Byte empfangen werden kann



mul_16x16:
push zeichen
clr temp1 ; 32 Bit Akku löschen
clr temp2
clr temp3
clr temp4
clr zeichen ; Null, für Carry-Addition

mul adlow, temp5 ; erste Multiplikation
add temp1, r0 ; und akkumulieren
adc temp2, r1

mul adhigh, temp5 ; zweite Multiplikation
add temp2, r0 ; und gewichtet akkumlieren
adc temp3, r1

mul adlow, temp6 ; dritte Multiplikation
add temp2, r0 ; und gewichtet akkumlieren
adc temp3, r1
adc temp4, zeichen ; carry addieren

mul adhigh, temp6 ; vierte Multiplikation
add temp3, r0 ; und gewichtet akkumlieren
adc temp4, r1

pop zeichen
ret


sende_einzelzeichen:
lds temp1,UCSR0A
sbrs temp1,UDRE0
rjmp sende_einzelzeichen
sts UDR0, zeichen ; und Zeichen ausgeben
ret

; mehrere Zeichen ausgeben, welche durch Z adressiert werden
; Anzahl in temp1

sende_zeichen:
lds temp1,UCSR0A
sbrs temp1,UDRE0
rjmp sende_zeichen
ld zeichen, Z+ ; Zeichen laden
sts UDR0, zeichen ; und Zeichen ausgeben
dec temp1
brne sende_zeichen
ret


; Tabelle mit Zahlen für die Berechung der Ziffern
; 1 Milliarde bis 1
Tabelle:
.dd 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1

BastelWastel
08.11.2010, 17:15
Deine Fehlerbeschreibung ist recht duenn...

albundy
09.11.2010, 11:04
nur mal kurz überflogen ...


ldi temp1, 1
rcall sende_zeichen



sende_zeichen:
lds temp1,UCSR0A
sbrs temp1,UDRE0
rjmp sende_zeichen
ld zeichen, Z+ ; Zeichen laden
sts UDR0, zeichen ; und Zeichen ausgeben
dec temp1
brne sende_zeichen
ret

das gibt schon mal eine Endlosschleife.