109 lines
3.8 KiB
C
109 lines
3.8 KiB
C
#include "ds18b20_ds2480.h"
|
|
#include <string.h>
|
|
|
|
static ds2480_status write_byte(ds2480 *bus, uint8_t value)
|
|
{
|
|
uint8_t echoed;
|
|
ds2480_status status = ds2480_byte(bus, value, &echoed);
|
|
if (status != DS2480_OK) return status;
|
|
return echoed == value ? DS2480_OK : DS2480_DATA;
|
|
}
|
|
|
|
static ds2480_status select_rom(ds2480 *bus, const uint8_t *rom)
|
|
{
|
|
uint8_t i;
|
|
ds2480_status status;
|
|
if (rom && (rom[0] != 0x28 || ds2480_crc8(rom, 8))) return DS2480_ARGUMENT;
|
|
status = ds2480_reset(bus);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, rom ? 0x55 : 0xCC);
|
|
if (status != DS2480_OK || !rom) return status;
|
|
for (i = 0; i < 8; ++i) {
|
|
status = write_byte(bus, rom[i]);
|
|
if (status != DS2480_OK) return status;
|
|
}
|
|
return DS2480_OK;
|
|
}
|
|
|
|
ds2480_status ds18b20_ds2480_next(ds2480 *bus, ds2480_search *search)
|
|
{
|
|
ds2480_status status;
|
|
do {
|
|
status = ds2480_search_next(bus, search);
|
|
if (status != DS2480_OK) return status;
|
|
} while (search->rom[0] != 0x28);
|
|
return DS2480_OK;
|
|
}
|
|
|
|
ds2480_status ds18b20_ds2480_convert(ds2480 *bus, const uint8_t rom[8])
|
|
{
|
|
ds2480_status status = select_rom(bus, rom);
|
|
if (status != DS2480_OK) return status;
|
|
return ds2480_power_byte(bus, 0x44, 750);
|
|
}
|
|
|
|
ds2480_status ds18b20_ds2480_read(ds2480 *bus, const uint8_t rom[8], uint8_t scratchpad[9])
|
|
{
|
|
uint8_t data[9], i;
|
|
ds2480_status status;
|
|
if (!rom || !scratchpad) return DS2480_ARGUMENT;
|
|
status = select_rom(bus, rom);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, 0xBE);
|
|
if (status != DS2480_OK) return status;
|
|
for (i = 0; i < 9; ++i) {
|
|
status = ds2480_byte(bus, 0xFF, &data[i]);
|
|
if (status != DS2480_OK) return status;
|
|
}
|
|
if (ds2480_crc8(data, 9)) return DS2480_CRC;
|
|
/* All-zero data has valid CRC but cannot be a DS18B20 scratchpad. */
|
|
if ((data[4] & 0x9F) != 0x1F) return DS2480_DATA;
|
|
memcpy(scratchpad, data, sizeof data);
|
|
return DS2480_OK;
|
|
}
|
|
|
|
ds2480_status ds18b20_ds2480_temperature(ds2480 *bus, const uint8_t rom[8], int16_t *raw)
|
|
{
|
|
uint8_t data[9], undefined;
|
|
uint16_t value;
|
|
int32_t signed_value;
|
|
ds2480_status status;
|
|
if (!raw) return DS2480_ARGUMENT;
|
|
status = ds18b20_ds2480_read(bus, rom, data);
|
|
if (status != DS2480_OK) return status;
|
|
undefined = (uint8_t)(3 - ((data[4] >> 5) & 3));
|
|
value = (uint16_t)((uint16_t)data[0] | ((uint16_t)data[1] << 8));
|
|
value &= (uint16_t)~((1U << undefined) - 1U);
|
|
signed_value = value & 0x8000 ? (int32_t)value - 65536 : (int32_t)value;
|
|
if (signed_value < -55 * 16 || signed_value > 125 * 16) return DS2480_DATA;
|
|
*raw = (int16_t)signed_value;
|
|
return DS2480_OK;
|
|
}
|
|
|
|
ds2480_status ds18b20_ds2480_configure(ds2480 *bus, const uint8_t rom[8],
|
|
int8_t th, int8_t tl, uint8_t resolution, uint8_t save)
|
|
{
|
|
uint8_t data[9], config;
|
|
ds2480_status status;
|
|
if (!rom || resolution < 9 || resolution > 12) return DS2480_ARGUMENT;
|
|
config = (uint8_t)(0x1F | ((resolution - 9) << 5));
|
|
status = select_rom(bus, rom);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, 0x4E);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, (uint8_t)th);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, (uint8_t)tl);
|
|
if (status != DS2480_OK) return status;
|
|
status = write_byte(bus, config);
|
|
if (status != DS2480_OK) return status;
|
|
status = ds18b20_ds2480_read(bus, rom, data);
|
|
if (status != DS2480_OK) return status;
|
|
if (data[2] != (uint8_t)th || data[3] != (uint8_t)tl || data[4] != config)
|
|
return DS2480_DATA;
|
|
if (!save) return DS2480_OK;
|
|
status = select_rom(bus, rom);
|
|
if (status != DS2480_OK) return status;
|
|
return ds2480_power_byte(bus, 0x48, 12);
|
|
}
|