Pfad: Home => AVR-Übersicht => Binäres Rechnen => Festkommazahl => 8-Bit-Wandlung

Assembler Quelltext der 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