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