www.mikrocontroller.net

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


Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: aha (Gast)
Datum:

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

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: spess53 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

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

MfG Spess

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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%20Dig...

@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.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: RENGEL (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ich habs jetzt so:

in r24 ist das lowbyte und r25 das high byte:
  ldi r22, 25
  mul r25, r22

  mov r25, r0
  
  ror r24
  ror r23
  ror r24
  ror r23
  ror r24
  ror r23

  lsr r23
  lsr r23
  lsr r23
  lsr r23
  lsr r23  


  add r25, r24
    
  ldi r22, 50
  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?

Autor: RENGEL (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also ungenau wirds bei mir nur hier:
  ror r24
  ror r23
  ror r24
  ror r23
  ror r24
  ror r23

  lsr r23
  lsr r23
  lsr r23
  lsr r23
  lsr r23  


  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.

Autor: Rainer Engelhardt (rengel)
Datum:

Bewertung
0 lesenswert
nicht 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)

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.