2023-08-09 22:15:34 +03:00

136 lines
3.9 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "dstemperature.h"
uint8_t DallasTemp_ReadScratchpad(uint8_t *scratchpad) {
if (!OneWire_SkipROM()) return 0;
OneWire_WriteByte(DS18B20_CMD_RSCRATCHPAD);
for (uint8_t i = 0; i < 8; i++) {
scratchpad[i] = OneWire_ReadByte();
}
uint8_t calculated_crc = OneWire_CRC8_Update(scratchpad, 8);
uint8_t crc = OneWire_ReadByte();
if (calculated_crc != crc) return 0;
return 1;
}
// TODO parasite power
uint8_t DallasTemp_CopyScratchpad(void) {
if (!OneWire_Presence()) return 0;
OneWire_SkipROM();
OneWire_WriteByte(DS18B20_CMD_CPSCRATCHPAD);
_delay_ms(10); // если паразитное питание то далее делать сброс
return 1;
}
void DallasTemp_WriteScratchpad(uint8_t *data) {
uint8_t i = 3;
OneWire_SkipROM();
OneWire_WriteByte(DS18B20_CMD_WSCRATCHPAD);
do {
OneWire_WriteByte(*data++);
} while (--i);
DallasTemp_CopyScratchpad();
}
void DallasTemp_SetResolution(DallasSensor *Sensor, uint8_t r) {
DallasTemp_ReadScratchpad(Sensor->SCRATCHPAD);
uint8_t data[3] = { Sensor->SCRATCHPAD[2], Sensor->SCRATCHPAD[3], 0x7f };
switch(r) {
case 12:
data[2] = 0x7f;
break;
case 11:
data[2] = 0x5f;
break;
case 10:
data[2] = 0x3f;
break;
case 9:
data[2] = 0x1f;
break;
default:
data[2] = 0x7f;
break;
}
DallasTemp_WriteScratchpad(data);
}
uint8_t DallasTemp_Convert(void) {
if (!OneWire_Presence()) return 0;
OneWire_WriteByte(ONE_WIRE_SKIPROM);
OneWire_WriteByte(DS18B20_CMD_CONVERTTEMP);
return 1;
}
DallasSensorError DallasTemp_CheckError(DallasSensor* Sensor) {
/* Нету присутствия */
if (!OneWire_Presence()) return ERR_NO_PRESENCE;
/* Семейный код неверный */
OneWire_ReadROM(Sensor->ROM);
if (Sensor->ROM[0] != DS18B20_CONST_FAMILY_CODE) return ERR_F_CODE_INVALID;
/* Ошибка CRC8 для ОЗУ */
if (!DallasTemp_ReadScratchpad(Sensor->SCRATCHPAD)) return ERR_CRC8_RAM;
/* Все ОК */
return 0;
}
void DallasTemp_GetTemperature(DallasSensor *Sensor) {
/* Читаем ОЗУ для определения нужной задержки */
if (!DallasTemp_ReadScratchpad(Sensor->SCRATCHPAD)) return;
/* Оцифровка */
if (!DallasTemp_Convert()) return;
/* Ждем необходимое кол-во времени в зависимости от разрядности АЦП */
if (!(~Sensor->SCRATCHPAD[4] & 0x60)) {
_delay_ms(750);
} else if (!(~Sensor->SCRATCHPAD[4] & 0x40)) {
_delay_ms(375);
} else if (!(~Sensor->SCRATCHPAD[4] & 0x20)) {
_delay_ms(188);
} else {
_delay_ms(94);
}
/* Читаем еще раз ОЗУ для получения актуальной температуры и проверки валидности данных */
if (!DallasTemp_ReadScratchpad(Sensor->SCRATCHPAD)) {
Sensor->CRC_ERROR = 1;
return;
}
Sensor->CRC_ERROR = 0;
Sensor->TEMPERATURE = ((Sensor->SCRATCHPAD[1] << 8) | Sensor->SCRATCHPAD[0]) / 16;
/*
* Двойное дополнение для дробной части если минусовая температура:
* проверяем что последние пять битов в старшем байте температуры стоят в единице
*/
if (!(~Sensor->SCRATCHPAD[1] & 0xf8)) {
Sensor->T_NEGATIVE = 1;
Sensor->SCRATCHPAD[0] = -Sensor->SCRATCHPAD[0];
} else {
Sensor->T_NEGATIVE = 0;
}
/**
* Получаем дробную часть через битовую маску 0x0f, умножаем для получения точности.
*/
Sensor->TEMPERATURE_FRACTION = ((Sensor->SCRATCHPAD[0] & 0x0f) * 1000) / 16;
}
//float DallasTemp_GetFloatTemperature(DallasSensor *Sensor) {
// DallasTemp_GetTemperature(Sensor);
// return (float)((float)Sensor->TEMPERATURE + ((float)Sensor->TEMPERATURE_FRACTION / 1000));
//}