Forum: Mikrocontroller und Digitale Elektronik DS18B20 Darstellung von negativen Zahlen im Zweierkomplement?


von Anon A. (anon1234)


Angehängte Dateien:

Lesenswert?

Halli hallo,
ich bin gerade im Datenblatt des 1-wire digital thermometers DS18B20 
über eine sache gestolpert, die mich ziemlich wundert.
Die Messwertes werden beim DS18B20 in zwei Byte dargestellt.
Bit 0 - Bit 3 vom niederwertigen Byte stellen die nachkommastellen dar.
Bit 4 vom niederwertigen Byte - Bit 2 vom höherwertigen Byte stellt die 
ganzen Zahlen des Messwertes dar.
Die restlichen Bits sind '1' bei einer negative Zahl und '0' bei einer 
positiven Zahl.

Nun heißt es in der Beschreibung im Datenblatt, dass negative Messwerte 
im Zweierkomplement dargestellt werden.
1
 
2
The temperature data is stored as a 16-bit sign-extended
3
two’s complement number in the temperature register (see Figure 2). The sign bits (S) indicate if the
4
temperature is positive or negative: for positive numbers S = 0 and for negative numbers S = 1.

Das bedeutet meiner Meinung nach,
1. alle Bits negieren (bis auf die Nachkommastellen natürlich)
2. neue zahl + 1 = zahl in zweierkomplement darstellung

Die Beispiele die das Datenblatt danach gibt passen meiner Meinung nach 
aber nicht zu der Aussage, dass zweierkomplement benutzt wird.

Denn der Wert -10 ist beispielsweise mit
11110101 dargestellt

Das ist einfach nur der Wert 10 in negierter Form, aber ohne die 
addition von 1.
Meine Frage ist jetzt:
ist die Aussage falsch, dass die Sensoren das zweierkomplement 
verwenden, oder sind einfach die Beispiele falsch ODER bin ich gerade 
einfach zu doof :) ?

Das Datenblatt, sowie ein Screeshot von den Beispielen habe ich 
angehängt

Wenn mir jemand weiter helfen könnte, würde ich mich freuen :)
Viele Grüße

anon1234

von Chris (Gast)


Lesenswert?

Anon Anon schrieb:
> Das bedeutet meiner Meinung nach,
> 1. alle Bits negieren (bis auf die Nachkommastellen natürlich)
> 2. neue zahl + 1 = zahl in zweierkomplement darstellung

Dein Punkt bei 1. ist nicht korrekt: du musst natürlich auch die 
Nachkommastellen negieren. Der Rest ist korrekt. Dann sollten auch die 
Beispiele aus dem Datenblatt passen.

von Cyblord -. (cyblord)


Lesenswert?

Dass die Werte korrekt im Zweierkomplement vorliegen, sieht man auch 
daran dass sie in C, wenn man die Rohdaten in einen signed integer 
steckt, völlig korrekt sind. Auch die Negativen.

von Karl H. (kbuchegg)


Lesenswert?

Anon Anon schrieb:

> 1. alle Bits negieren (bis auf die Nachkommastellen natürlich)

Wobei du dir das Leben einfacher machen kannst, wenn du die 
Nachkommastellen nicht als Nachkommastellen auffasst, sondern das ganze 
so darstellst, dass du vom DS ganz einfach das 16-fache des realen 
Wertes bekommst.

Der DS schickt dir also zur Darstellung von -55°C nicht -55, sondern das 
16 fache davon. Das wäre also -880. Desssen 2-er Komplement-Darstellung 
lautet 0xFC90 (was mit dem Datenblatt übereinstimmt). Oder: Der DS will 
dir mitteilen, dass die aktuelle Temperatur -10.125° beträgt. Er schickt 
dir das 16-fache von 10.125, dezimal sind das 162, allerdings -162. Die 
2-er Komplementdarstellung von -162 lautet 0xFF5E, was wieder mit dem 
Datenblatt übereinstimmt.

von Anon A. (anon1234)


Lesenswert?

Ooh okay,
das mit den Nachkommastellen hatte ich nicht bedacht, dann macht auch 
alles einen Sinn.
Vielen vielen Dank für den Tipp!

von Jo (Gast)


Lesenswert?

Hallo,

ich muss hier nochmal nachhaken, denn ich bin auf dasselbe Problem 
gestoßen, und verstehe die Logik immer noch nicht.

Mich interessieren erstmal nur die ganzzahligen Anteile, also ohne 
Nachkommastelle, also Bit 11 bis Bit 4. Diese sind im Datenblatt 
folgendermaßen angegeben (Seite 6):

-10 = 1110101 = invertiert 0001010 = 10 (ohne Addition von 1)
-25 = 1100110 = invertiert 0011001 = 25 (ohne Addition von 1)
-55 = 1001001 = invertiert 0001010 = 54 (statt 55, ohne Addition von 1)

Also beim letzten Wert -55 wird es meiner Meinung nach inkonsistent, 
oder darf ich den Nachkommaanteil hier nicht vernachlässigen? Aber wie 
wirkt dieser sich dann auf den ganzzahligen Anteil aus?

von Jo (Gast)


Lesenswert?

Hallo,

ich muss hier nochmal nachhaken, denn ich bin auf dasselbe Problem 
gestoßen, und verstehe die Logik immer noch nicht.

Mich interessieren erstmal nur die ganzzahligen Anteile, also ohne 
Nachkommastelle, also Bit 11 bis Bit 4. Diese sind im Datenblatt 
folgendermaßen angegeben (Seite 6):

-10 = 1110101 = invertiert 0001010 = 10 (ohne Addition von 1)
-25 = 1100110 = invertiert 0011001 = 25 (ohne Addition von 1)
-55 = 1001001 = invertiert 0110110 = 54 (statt 55, ohne Addition von 1)

Also beim letzten Wert -55 wird es meiner Meinung nach inkonsistent, 
oder darf ich den Nachkommaanteil hier nicht vernachlässigen? Aber wie 
wirkt dieser sich dann auf den ganzzahligen Anteil aus?

von (prx) A. K. (prx)


Lesenswert?

KHB hatte das völlig korrekt beschrieben. Lass dich durch die Erwähnung 
von Vor- und Nachkommastellen nicht kirre machen und betrachte das als 
ganz normale 16-Bit "int" mit Vorzeichen, die Sechzehntel-Grad 
darstellt. Stinknormale Zweierkomplementdarstellung dieser 
Sechzehntel-Grade. Vor- und Nachkommastellen getrennt zu betrachten ist 
nicht sinvoll.

: Bearbeitet durch User
von Falk B. (falk)


Lesenswert?

Eben, siehe Festkommaarithmetik.

von Peter D. (peda)


Lesenswert?

A. K. schrieb:
> Vor- und Nachkommastellen getrennt zu betrachten ist
> nicht sinvoll.

Ja, das ergibt Murks.
Im einfachsten Fall castet man den Wert nach signed, teilt durch 16.0 
und weißt es einem float zu.
1
float calc_temp( uint8_t lb, uint8_t hb)
2
{
3
  return (int16_t)(lb | hb<<8) / 16.0;
4
}

von Peter M. (r2d3)


Lesenswert?

Jo schrieb:
> Also beim letzten Wert -55 wird es meiner Meinung nach inkonsistent,
> oder darf ich den Nachkommaanteil hier nicht vernachlässigen? Aber wie
> wirkt dieser sich dann auf den ganzzahligen Anteil aus?

Du darfst den Nachkommateil deswegen nicht vernachlässigen, weil er 
bestimmt, ob sich der Vorkommateil um Eins erhöht oder nicht.

Nur wenn der Nachkommateil aus Nullen besteht, führt die Addition von 
Eins nach Invertierung dazu, dass einer Dominosteinkette gleich die Bits 
von hinten nach vorne umkippen und ein Übertrag von Eins an die Stelle 
2^0 erfolgt.

von Chris H. (Firma: Selbständig Denkender) (keiningenieur)


Lesenswert?

Jo schrieb:
> Also beim letzten Wert -55 wird es meiner Meinung nach inkonsistent,
> oder darf ich den Nachkommaanteil hier nicht vernachlässigen? Aber wie
> wirkt dieser sich dann auf den ganzzahligen Anteil aus?

Beispiel anhand der -0,5°C:

-0,5 = FFF8h das erste F von links beschreibt ob der Wert + oder - ist 
mit 0... oder F...  . Im nächsten Schritt muss nur ein Vegleich darauf 
gestartet werden welche Berechnung ausgeführt werden soll.

Bei 0, also Plus im ersten Nibble teilst du den Wert durch 16 und hast 
dein Ergebnis BSP +0,5°C = 0008h / 16 = 0,5°C

Bei F, also Minus im ersten Nibble bei

-0,5°C = FFF8h                = 1111 1111 1111 1000² jetzt wirds
einfach negiert (1er Komplemnt) 0000 0000 0000 0111 und dann
einmal +1 (2er Komplement)    = 0000 0000 0000 1000

Wenn du das für jeden Wert durchgehst ist die Konsistenz gegeben:

-55°C = FC90h = 1111 1100 1001 0000 mit Negation wirds zu
com/neg 036Fh = 0000 0011 0110 1111
                                 +1
        0370h = 0000 0011 0111 0000 = 880 dez / 16 = 55°C
unter Beachtung des ersten Nibbles ist es dann -55°C

: Bearbeitet durch User
von zyxw (Gast)


Lesenswert?


von (prx) A. K. (prx)


Lesenswert?

zyxw schrieb:
> Beitrag "DS18S20 - extended resolution bei Temperaturen um 0°C"

Hier geht es um den DS18B20, und der liefert eine andere Darstellung als 
der DS18S20. Der B liefert bereits fix und fertige Sechzehntel ab, 
während der S an gleicher Stelle nur halbe Grade liefert, und man für 
höhere Auflösung umständlich nacharbeiten muss.

: Bearbeitet durch User
von zyxw (Gast)


Lesenswert?

> und man für höhere Auflösung umständlich nacharbeiten muss.
Findest du diese zwei Zeilen sehr umständlich?
1
  t12 = 3 + 8 * a[0] - ((a[6] - 1) & 7);//alternative way of calculation
2
  if(a[1]){t12 -= 128 * 16;}  //correct by -128°

Damit hat man das selbe Format (hier t12) wie der DS18B20.
Nach diesen 2 Zeilen kann man genau so gut den 12Bit-Wert vom DS18B20 
verwenden:
1
const PROGMEM char
2
  g[16]="0011233455667889", //first  fractional digit
3
  h[16]="0639518406395184"; //second fractional digit
4
5
  unsigned char d[9];       //Dallas DS18x20 Scratchpad
6
  char t;                   //temperature in absolute degrees
7
  char f;                   //fractionals (1/16°) of absolute degrees
8
  char c,s;                 //sign (if zero, the sign was printed already)
9
  int  t12;                 //12bit temperature value (compatible with DS18B20)
10
11
//t12=3+8*a[0]-((a[6]-1)&7);  //alternative way of calculation
12
//if(a[1]){t12-=128*16;}      //correct by -128°, format is now the same as DS18B20
13
14
  t12=(d[1]<<8)+d[0];       //12bit-temperature from DS18B20 scratchpad
15
  if(t12>=0){s='+';}        //calc absolute temp
16
  else{t12=-t12;s='-';}
17
18
  f=t12&15;                 //fractionals
19
  t=t12>>4;                 //must be signed int  for the calculation of tens-digit (while)
20
21
  if(t>99){putch(s);s=0;    //absolute temp is higher than 99 (and lower than 128)
22
    putch('1');t-=100;}     //sign-digit is the sign, hund-digit is 1
23
  else{putch(' ');          //absolute temp is lower than 100, sign-digit is a space
24
    if(t>9){putch(s);s=0;}  //if 10..99: hundreds-digit is the sign
25
    else    putch(' ');}    //if  0.. 9: hundreds-digit is a space
26
27
  c='0'-1;                  //calculate tens
28
  while(c++,(t-=10)>=0);    //this should be faster than c='0';while((t-=10)>=0)c++;
29
  if(s)putch(s);            //if sign was not printed yet, do it now at tens-digit
30
  else putch(c);            //tens-digit
31
32
  putch(58+t);putch(',' );  //ones-digit   '0'+10+t, as t is negative here
33
  putch(g[f]);putch(h[f]);  //the fractional digits are not calculated
34
  putch('°' );putch('C' );  //but stored in 2 arrays

[Mod: Typo korrigiert]

: Bearbeitet durch Moderator
Beitrag #7090886 wurde von einem Moderator gelöscht.
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.