mirror of
https://github.com/sergeyyarkov/attiny45v_thermometer.git
synced 2026-10-11 02:08:56 +03:00
131 lines
3.4 KiB
C
131 lines
3.4 KiB
C
#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); если паразитное питание то ждем 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));
|
||
//}
|