attiny45v_thermometer/dstemperature.c
2023-08-05 20:33:08 +03:00

131 lines
3.3 KiB
C
Raw 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) {
OneWire_SkipROM();
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_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));
//}