Files
templates/c/ds18b20-ds2480/ds18b20_ds2480.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);
}