Hallo,
Im Datenblatt vom DS18S20 steht, das fur den Wert 0xFFFF ich eine
Temperatur von -0.5C bekommen sollte.
Erstmal was funktioniert: 0xFF92 soll -55.0 sein:
0xFF92 = 0b1111111110010010
LSB = 0b10010010
MSB = 0b11111111
Bit 0 von LSB ist 0, also hat der Wert eine 0 nach dem komma.
Vom MSB geht hevor das es ein negativer Wert ist.
Ich invertiere die bits und bekomme 0b01101101, da es sich aber um einen
7bit Wert handelt, ist der wert 0b00110110, dazu +1 und wir haben
0b00110111 was decimal 55 entspricht. Funktioniert also prima.
Jetzt das was ich nicht verstehe:
0xFFFF = 0b1111111111111111
LSB = 0b11111111
MSB = 0b11111111
Bit 0 von LSB ist 1, also hat der Wert ein 5 nach dem komma.
Sign bit ist 1, also ist es ein negativer Wert.
Ich invertiere die bits und bekomme 0b00000000, da es sich aber um einen
7bit wert handelt, ist der wert 0b0000000, dazu +1 und wir haben
0b0000001 was decimal 1 entspricht, dazu 0.5, ergibt zusammen 1.5.
Wieso steht im Datenblatt 0.5 ? Kann ich nicht richtig zahlen ?
Grus an Alle
Hallo,
es gibt noch eine andere Möglichkeint, eine Zahl im zweierkomplement in
eine Zahl im Zehnersystem umzuwandeln:
Das niederwertigste Bit in MS Byte hat die Wertigkeit -2^7, das
höchstwertigste Bit in LS Byte hat die Wertigkeit 2^6, das nächste Bit
die Wertigkeit 2^5 ... das niederwertigste Bit in LS Byte hat die
Wertigkeit 2^(-1) = 1/2.
0xFFFF kann man dann schreiben als (die 7 höchstwertigsten Bits in MS
Byte kann man weglassen, das ist sowieso nur das Vorzeichenbit):
11111111.1 = -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 + 0,5 = -0,5, was auch
im Datenblatt steht
vgl. auch
http://de.wikipedia.org/wiki/Zweierkomplement#Umwandlung_ins_Dezimalsystem
im Abschnitt "Umwandlung ins Dezimalsystem" unten.
Wo dein Denkfehler ist weiß ich gerade nicht, vielleicht sieht das ja
jemand anderes...
Viele Grüße
Michael
Scheinbar funktioniert die Hilfsregel "invertieren + 1 addieren" nur,
wenn es sich um eine Zahl aus Z (also keine Nachkommastellen) handelt
Viele Grüße
Michael
Hallo Michael,
ich kenne jetzt deine Hilfsregel nicht, aber vollständig wäre die
Anweisung ja:
invertieren -> rechts shiften -> +1
Wenn die Reihenfolge tatsächlich so wäre:
invertieren -> +1 -> rechts shiften
würde sie immer stimmen. Scheint mir auch logischer zu sein.
W. P. schrieb:> 0b0000001 was decimal 1 entspricht, dazu 0.5, ergibt zusammen 1.5.
****
Deine eigentliche Zahl ist ja negativ. Also 0.5 wegzählen. Nicht dazu.
Du kannst es auch so sehen:
0xFFFF ist die erste negative Zahl, die überhaupt möglich ist. Da bei
dir die 'Zahlauflösung' 0.5 Einheiten beträgt, ist die erste negative
Zahl dann eben -0.5 ( -1 * 0.5 -> -0.5 )
> Bit 0 von LSB ist 1, also hat der Wert ein 5 nach dem komma.
Hier ist dein Denkfehler.
Du verwechselst da 2 Operationen.
Die eine Operation ist: An die Zahl eine Stelle anhängen (und sei es nur
eine Nachkommastelle)
Die andere ist: Zu einer Zahl ein ander (eben 0.5) vorzeichenrichtig
addieren.
Bei positiven Zahlen liefern beide Operationen ein identisches Ergebnis.
Nur bei negativen eben nicht.
-x + 0.5
ist eben nicht dasselbe wie
-( x + 0.5)
Karl Heinz Buchegger schrieb:> Deine eigentliche Zahl ist ja negativ. Also 0.5 wegzählen. Nicht dazu.
Mann bin ich blod... hast recht, ein Kerl will was mit uCs machen, kann
aber nicht bis zwei zahlen :)
Tausend Mal danke :)
W. P. schrieb:> Karl Heinz Buchegger schrieb:>> Deine eigentliche Zahl ist ja negativ. Also 0.5 wegzählen. Nicht dazu.>> Mann bin ich blod... hast recht, ein Kerl will was mit uCs machen, kann> aber nicht bis zwei zahlen :)>> Tausend Mal danke :)
Und ich hoffe, das das nur eine theoretische Überlegung war. In einer
Programmiersprache (zb C), die mit 2-er Komplement umgehen kann,
brauchst du dich nicht darum kümmern.
Ber der Ausgabe stellst du einfach fest, ob die Zahl negativ ist oder
nicht und malst dann einfach ein '-' auf die Anzeige. In diesem Fall
nimmst du dann auch das nagative der Zahl (um sie positiv zu machen) und
gibst die einfach aus. Für den Vorkommaanteil dividierst du die Zahl
durch 2, dann malst du einen Punkt hin und wenn der Moduls der (jetzt
positiven) Zahl ungleich 0 ist malst du noch eine 5 hinten drann.
if( zahl < 0 )
{
Ausgabe( '-' )
Zahl = -Zahl
}
AusgabeInt( Zahl / 2 )
Ausgabe( '.' )
if( Zahl % 2 == 0 )
Ausgabe( '0' )
else
Ausgabe( '5' )
W. P. schrieb:> Ok, int16_t anstatt vom int.
Welchen µC benutzt du?
Ich hatte die int16_t nachgebessert um das etwas klarer zu machen. Auf
einem AVR ist int16_t und int allerdings identisch.
Den Quellcode habe ich auf meinem Laptop per gcc am laufen.
Prototyping befor ich das auf meinem ATMEGA8 schmeisse.
Die LCD routinen fur mein Projekt habe ich schon, und laufen auf dem AVR
ok.
Jetzt noch eine Routine fur zwei DS18S20 an zwei Pins basteln und
fertig.
Ich weiss, ist Pinverschwendung, aber ich brauch nichts anderes
anzuschliesen auser noch einen Relais und es macht das auslesen /
austauschen der Sensoren einfacher.
W. P. schrieb:> Den Quellcode habe ich auf meinem Laptop per gcc am laufen.>> Prototyping befor ich das auf meinem ATMEGA8 schmeisse.
Dann ist alles klar.
Am PC ist ein int heutzutage 32 Bit gross.
Daher: Bei solchen Sachen explizit sein (hätt ich gleich tun sollen.
Sorry)