Pfad:
Home =>
AVR-Übersicht =>
Binäres Rechnen =>
Festkommazahl => 8-Bit-Wandlung
(This page in English:
)
Umwandlung einer 8-Bit-Zahl in eine dreistellige Festkommazahl
; Demonstriert Fließkomma-Umwandlung in
; Assembler, (C)2003 www.avr-asm-tutorial.net
;
; Die Aufgabe: Ein 8-Bit-Analog-Wandler-Signal
; in Binärform wird eingelesen, die Zahlen
; reichen von hex 00 bis FF.
; Diese Zahlen sind umzurechnen in eine
; Fließkommazahl zwischen 0,00 bis 5,00
; Volt.
;
; Der Programmablauf:
; 1. Multiplikation mit 502 (hex 01F6).
; Dieser Schritt multipliziert die Zahl mit
; den Faktoren 500 und 256 und dividiert
; mit 255 in einem Schritt.
; 2. Das Ergebnis wird gerundet und das letzte
; Byte abgeschnitten.
; Dieser Schritt dividiert durch 256, indem
; das letzte Byte des Ergebnisses ignoriert
; wird. Davor wird das Bit 7 des Ergebnisses
; abgefragt und zum Runden des Ergebnisses
; verwendet.
; 3. Die erhaltene Zahl wird in ASCII-Zeichen
; umgewandelt und mit einem Dezimalpunkt
; versehen.
; Das Ergebnis, eine Ganzzahl zwischen 0 und
; und 500 wird in eine Dezimalzahl verwan-
; delt und in der Form 5,00 als Fließkomma-
; zahl in ASCII-Zeichen dargestellt.
;
; Die verwendeten Register:
; Die Routinen benutzen die Register R8 bis R1,
; ohne diese vorher zu sichern. Zusätzlich wird
; das Vielzweckregister rmp verwendet, das in
; der oberen Registerhälfte liegen muss. Bitte
; beachten, dass diese verwendeten Register
; nicht mit anderen Verwendungen in Konflikt
; kommen können.
;
; Zu Beginn wird die 8-Bit-Zahl im Register
; R1 erwartet.
;
; Die Multiplikation verwendet R4:R3:R2 zur
; Speicherung des Multiplikators 502 (der
; bei der Berechnung maximal 8 mal links ge-
; schoben wird - Multiplikation mit 2). Das
; Ergebnis der Multiplikation wird in den Re-
; gistern R7:R6:R5 berechnet.
; Das Ergebnis der sogenannten Division durch
; 256 durch Ignorieren von R5 des Ergebnisses
; ist in R7:R6 gespeichert. Abhängig von Bit
; 7 in R5 wird zum Registerpaar R7:R6 eine
; Eins addiert. Das Ergebnis in R7:R6 wird
; in das Registerpaar R2:R1 kopiert.
; Die Umwandlung der Binärzahl in R2:R1 in
; eine ASCII-Zeichenfolge verwendet das Paar
; R4:R3 als Divisor für die Umwandlung. Das
; Ergebnis, der ASCII-String, ist in den Re-
; gistern R5:R6:R7:R8 abgelegt.
;
; Weitere Bedingungen:
; Die Umwandlung benutzt Unterprogramme, daher
; muss der Stapel funktionieren. Es werden
; maximal drei Ebenen Unterprogrammaufrufe
; verschachtelt (benötigt sechs Byte SRAM).
;
; Umwandlungszeiten:
; Die gesamte Umwandlung benötigt 228 Taktzyklen
; maximal (Umwandlung von $FF) bzw. 79 Takt-
; zyklen (Umwandlung von $00). Bei 4 MHz Takt
; entspricht dies 56,75 Mikrosekunden bzw. 17,75
; Mikrosekunden.
;
; Definitionen:
; Register
.DEF rmp = R16 ; als Vielzweckregister verwendet
;
; AVR-Typ
; Getestet für den Typ AT90S8515, die Angabe
; wird nur für den Stapel benötigt. Die Routinen
; arbeiten auf anderen AT90S-Prozessoren genauso
; gut.
.NOLIST
.INCLUDE "8515def.inc"
.LIST
;
; Start des Testprogramms
;
; Schreibt eine Zahl in R1 und startet die Wand-
; lungsroutine, nur für Testzwecke.
;
.CSEG
.ORG $0000
rjmp main
;
main:
ldi rmp,HIGH(RAMEND) ; Richte den Stapel ein
out SPH,rmp
ldi rmp,LOW(RAMEND)
out SPL,rmp
ldi rmp,$FF ; Wandle FF um
mov R1,rmp
rcall fpconv8 ; Rufe die Umwandlungsroutine
no_end: ; unendliche Schleife, wenn fertig
rjmp no_end
;
; Ablaufssteuerung der Umwandlungsroutine, ruft die
; verschiedenen Teilschritte auf
;
fpconv8:
rcall fpconv8m ; Multipliziere mit 502
rcall fpconv8r ; Runden und Division mit 256
rcall fpconv8a ; Umwandlung in ASCII-String
ldi rmp,'.' ; Setze Dezimalpunkt
mov R6,rmp
ret ; Alles fertig
;
; Unterprogramm Multiplikation mit 502
;
; Startbedingung:
; +--+
; |R1| Eingabezahl, im Beispiel $FF
; |FF|
; +--+
; +--+--+--+
; |R4|R3|R2| Multiplikant 502 = $00 01 F6
; |00|01|F6|
; +--+--+--+
; +--+--+--+
; |R7|R6|R5| Resultat, im Beispiel 128.010
; |01|F4|0A|
; +--+--+--+
;
fpconv8m:
clr R4 ; Setze den Multiplikant auf 502
ldi rmp,$01
mov R3,rmp
ldi rmp,$F6
mov R2,rmp
clr R7 ; leere Ergebnisregister
clr R6
clr R5
fpconv8m1:
or r1,R1 ; Prüfe ob noch Bits 1 sind
brne fpconv8m2 ; Noch Einsen, mach weiter
ret ; fertig, kehre zurück
fpconv8m2:
lsr R1 ; Schiebe Zahl nach rechts (teilen durch 2)
brcc fpconv8m3 ; Wenn das niedrigste Bit eine 0 war,
; dann überspringe den Additionsschritt
add R5,R2 ; Addiere die Zahl in R4:R3:R2 zum Ergebnis
adc R6,R3
adc R7,R4
fpconv8m3:
lsl R2 ; Multipliziere R4:R3:R2 mit 2
rol R3
rol R4
rjmp fpconv8m1 ; Wiederhole für das nächste Bit
;
; Runde die Zahl in R7:R6 mit dem Wert von Bit 7 von R5
;
fpconv8r:
clr rmp ; Null nach rmp
lsl R5 ; Rotiere Bit 7 ins Carry
adc R6,rmp ; Addiere LSB mit Übertrag
adc R7,rmp ; Addiere MSB mit Übertrag
mov R2,R7 ; Kopiere den Wert nach R2:R1 (durch 256 teilen)
mov R1,R6
ret
;
; Wandle das Wort in R2:R1 in einen ASCII-Text in R5:R6:R7:R8
;
; +---+---+
; + R2| R1| Eingangswert 0..500
; +---+---+
; +---+---+
; | R4| R3| Dezimalteiler
; +---+---+
; +---+---+---+---+
; | R5| R6| R7| R8| Ergebnistext (für Eingangswert 500)
; |'5'|'.'|'0'|'0'|
; +---+---+---+---+
;
fpconv8a:
clr R4 ; Setze Dezimalteiler auf 100
ldi rmp,100
mov R3,rmp
rcall fpconv8d ; Hole ASCII-Ziffer durch wiederholtes Abziehen
mov R5,rmp ; Setze Hunderter Zeichen
ldi rmp,10 ; Setze Dezimalteiler auf 10
mov R3,rmp
rcall fpconv8d ; Hole die nächste Ziffer
mov R7,rmp
ldi rmp,'0' ; Wandle Rest in ASCII-Ziffer um
add rmp,R1
mov R8,rmp ; Setze Einer Zeichen
ret
;
; Wandle Binärwort in R2:R1 in eine Dezimalziffer durch fortgesetztes
; Abziehen des Dezimalteilers in R4:R3 (100, 10)
;
fpconv8d:
ldi rmp,'0' ; Beginne mit ASCII-0
fpconv8d1:
cp R1,R3 ; Vergleiche Wort mit Teiler
cpc R2,R4
brcc fpconv8d2 ; Carry nicht gesetzt, subtrahiere Teiler
ret ; fertig
fpconv8d2:
sub R1,R3 ; Subtrahiere Teilerwert
sbc R2,R4
inc rmp ; Ziffer um eins erhöhen
rjmp fpconv8d1 ; und noch einmal von vorne
;
; Ende der Fließkomma-Umwandlungsroutinen
;
;
; Ende des Umwandlungstestprogramms
;
©2003 by http://www.avr-asm-tutorial.net