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.
Eine Division in ASM ...kann man als fortgesetzte Subtraktion mit schieben durchfuehren. Wie man's schriftlich machen wuerde eben.
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)
Hi Ich habe dir mal die relevanten Routinen meiner TSIC-Berechnung angehängt. MfG Spess
@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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.