The DS18B20 returns temperatures as 12-bit values, with the most significant bit being the sign bit. The remaining (highest or leftmost) 4 bits of the most significant byte are set to match the sign bit and can be ignored.

When the sign bit is 0, the remaining bits represent the (positive) temperature measured in sixteenths of a degree Celsius. When the sign bit is 1, the value represents a twos complement that encodes a negative value (again, in sixteenths of a degree Celsius).

All of this is discussed on pages 3 and 4 of the datasheet.

I posted a while back about using a single DS18B20 with a Netduino and using multiple DS18B20s with a Netduino with the help of godfroi's OneWireBus and DS18B20 classes. To obtain correct readings when the temperature is below 0° C, a small modification of the DS18B20 class is required.

Change the lines that read

return (float)data / 16f;

to this group of lines:

if (data < 2048) {

return (float)data / 16f;

}

else

{

return (float)-(~(data - 1) / 16f);

}

If the value is 2047 (binary 0111 1111 1111) or less, the sign bit is zero, so the value is positive. Dividing by a floating point value of 16 will give the positive temperature.

If the raw reading is 2048 (binary 1000 0000 0000) or more, the value is a negative number encoded as a twos complement. To convert this value,

- Subtract 1
- Reverse each bit using the ~ (bitwise not) operator converting each 0 to 1 and each 1 to 0.
- Divide by 16 (as a floating point value).
- Make the resulting value negative.