Forum: Mikrocontroller und Digitale Elektronik 16bit Wert in Floatzahl umrechnen (AVR Assembler)


von Gast (Gast)


Lesenswert?

hallo.

ich habe einen temperatursensor, der die temperatur als 11bit wert 
ausgibt an einen atmega8 angeschlossen. der 11bit wert liegt also in 
zwei 8bit registern vor.
im datenblatt des sensors steht zur umrechnung folgender c-code:
value_float = ((float)temp_value / 2047 * 200) - 50;

ich bin ehrlichgesagt etwas überfragt, was divisionen in assembler 
angeht...
wie rechne ich den vorliegenden bit-wert so um, dass ich die ganze zahl 
(bereich von -50 bis 130) in einem register und den wert hinter dem 
komma (auf eine nachkommastelle gerundet) in einem anderen register 
stehen habe? das vorzeichen sollte dann noch im negativ flag angegeben 
werden.

diese trennung von ganzzahl und kommazahl in 2 register wäre mir am 
liebsten, weil ich die zahlen dann einfach auf meinem lcd ausgeben kann 
und einfach von hand noch das minus ausgeben lasse wenn das 
entsprechende flag gesetzt ist und ich auch einfach das komma ausgeben 
kann. also:
[vorzeichen][ganzzahl (registerX)][,][kommastelle (registerY)]

wie würde man das anstellen? beispiel code wäre super!
ich wäre auch schon zufrieden, wenn statt der oberen formel einfach:
value_float=temp_value/10-50
durchgeführt wird...ist ja beinahe dasselbe.

von aha (Gast)


Lesenswert?

Eine Division in ASM ...kann man als fortgesetzte Subtraktion mit 
schieben durchfuehren. Wie man's schriftlich machen wuerde eben.

von Matthias L. (Gast)


Lesenswert?

zuerstmal bezweifle ich, dass das durch 2047 korrekt ist.

durch 2048 ist sicherlich besser und richtig.


>-50 bis 130)

Gehe ich recht in der Annahme, dass der WErtebereich von "temp_value"
zwischen 0..1843 liegt? (und das soll -50..+130 Grad werden)

von spess53 (Gast)


Angehängte Dateien:

Lesenswert?

Hi

Ich habe dir mal die relevanten Routinen meiner TSIC-Berechnung 
angehängt.

MfG Spess

von Gast (Gast)


Lesenswert?

@Matthias Lipinsky:

also 2047 ist schon richtig. schau mal auf der letzten seite. wenn man 
einfach mit 10 statt mit 2047/200 rechnet, entspricht jeder 0.1 wert 
einer bitstelle also noch 0-1800.
http://www.zmd.biz/pdf/IST_TSic_ZACwire_V2.3%20Digital%20Output_17-Oct-06.pdf

@spess53:

danke da muss ich mich jetzt erstmal reindenken. wozu ist denn die 
32/32bit division? so große zahlen kommen doch gar nicht vor.

von spess53 (Gast)


Lesenswert?

Hi

>danke da muss ich mich jetzt erstmal reindenken. wozu ist denn die
>32/32bit division? so große zahlen kommen doch gar nicht vor.

Doch -> rcall mul16x16_32.

MfG Spess

von RENGEL (Gast)


Lesenswert?

Mal davon abgesehen, dass das das Teil sowie so nur eine Genauigkeit von 
±0,1° hat, macht eine Division durch 2048 statt durch 2047 gerade mal 
einen Fehler von 0,05%. Ausserdem lässt sich dann viel leichter rechnen:
(Register / 256 * 25) - 50; die Division ist dann durch einfaches Shifte 
zu erledigen.

von Matthias L. (Gast)


Lesenswert?

>also 2047 ist schon richtig. schau mal auf der letzten seite

Das ist doch kein Datenblatt.

Wie heißt das Teil? Wo gibts ein DB?


>Ausserdem lässt sich dann viel leichter rechnen:
>(Register / 256 * 25) - 50

Noch besser. an kann die 256 noch weiter herausziehen:

         1
Temp = ----- [ 25*Register - 12800 ]
        256

Das Teile durch 256 kann man sich sparen, indem man einfach das Lowbyte 
ignoriert und das Highbyte als Tempwert nimmt.

von Gast (Gast)


Lesenswert?

ich habs jetzt so:

in r24 ist das lowbyte und r25 das high byte:
1
  ldi r22, 25
2
  mul r25, r22
3
4
  mov r25, r0
5
  
6
  ror r24
7
  ror r23
8
  ror r24
9
  ror r23
10
  ror r24
11
  ror r23
12
13
  lsr r23
14
  lsr r23
15
  lsr r23
16
  lsr r23
17
  lsr r23  
18
19
20
  add r25, r24
21
    
22
  ldi r22, 50
23
  sub r25, r22

das dividieren durch 256 kann ich mir ja sparen weil dann ja nur der 
wert um 1 register verschoben wird.

also (highbyte*256+lowbyte)/10 das wäre ja die temperatur. daraus wird 
bei mir highbyte*25+lowbyte/10 => highbyte*25+(lowbyte mod 8)
also das low byte 3 mal nach rechts geschoben und die rausgeschobenen 
bits in ein neue register getan. dann ist der wert in dem neuen register 
ungefähr der wert hinter dem komma. das dumme ist die nachkommastelle 
hat jetzt nur den bereich von 0-7...

wie könnte ich lowbyte/10 in asm schreiben? und den rest in ein neues 
register schreiben?

von RENGEL (Gast)


Lesenswert?

-           1
-  Temp = ----- [ 25*Register - 12800 ]
-          256
also ich würde dann schon eher Temp=(Register-512)/256*25 rechnen

Wie genau sll denn das Ganze werden? Wenn man das rausgeschobene Byte 
komplett wegschmeisst, wirft man den Nachkommateil der Division weg und 
der müsste ja nocheinmal 25x aufaddiert werden, da kann schon einiges 
zusammenkommen - also:
TempLo=LoByte*16+LoByte*8+LoByte -> HighByte der Summe zum Ergbnis von:
TempHi=RegHiByte*25 addieren = Vorkomma
LowByte der ersten Rechnung (TempLo) ist Nachkommateil, Bits gewichtet
mit 0.5, 0.25, 0.125 etc, d.h. je nach geforderter Anzahl an 
Nachkommastellen braucht man da wahrscheinlich nur die obersten drei 
oder vier Bits zu betrachten.

von Gast (Gast)


Lesenswert?

also ungenau wirds bei mir nur hier:
1
  ror r24
2
  ror r23
3
  ror r24
4
  ror r23
5
  ror r24
6
  ror r23
7
8
  lsr r23
9
  lsr r23
10
  lsr r23
11
  lsr r23
12
  lsr r23  
13
14
15
  add r25, r24

das ist die division durch 8 statt durch 10. und im register r23 steht 
dann ein wert zwischen 0..7 als nachkomma wert, der restwert im register 
r24 wird zu r25 addiert und stellt so den ganzzahl wert da. also 
wegschmeißen tue ich nichts.

nur statt /8 hätte ich gerne eine genauere operation, die mir vor- und 
nachkomma stelle in 2 register schreibt.

von Rainer E. (rengel)


Lesenswert?

Naja wenn Du nur durch 8 teilst brauchst Du auch keine Nachkommastelle 
mehr, da aus ursprünglich Reg/10.235 ist ungefähr Reg/10 schliesslich 
Reg/8 geworden ist.

Wie schon oben geschrieben:
nimm den 11-Bit Wert deines Bausteins
subtrahiere 512
VKtemp = HighByte MULS 25 (
NKtemp = LowByte MUL 25
das LowByte von NKtemp sind jetzt Deine Nachkommastellen: Bit7 = 0.5, 
Bit6 = 0.25 .. Bit0 = 1/256
das HighByte von NKtemp must Du noch auf VKtemp aufaddieren

Falls eine negative Temperatur herauskommt, ist nun die Vorkommazahl um 
eins zu negativ (+1) und vom Nachkommateil muss noch das 2er-Komplement 
gebildet werden (invertieren+1)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.