77 lines
2.9 KiB
C
77 lines
2.9 KiB
C
//
|
||
// Created by cfif on 03.12.2025.
|
||
//
|
||
#include <math.h>
|
||
#include <stdint.h>
|
||
|
||
// Значение температуры, возвращаемое если сумма результатов АЦП больше первого значения таблицы
|
||
#define TEMPERATURE_UNDER (-400)
|
||
// Значение температуры, возвращаемое если сумма результатов АЦП меньше последнего значения таблицы
|
||
#define TEMPERATURE_OVER 800
|
||
// Значение температуры соответствующее первому значению таблицы
|
||
#define TEMPERATURE_TABLE_START (-400)
|
||
// Шаг таблицы
|
||
#define TEMPERATURE_TABLE_STEP 50
|
||
|
||
/* Таблица суммарного значения АЦП в зависимости от температуры. От большего значения к меньшему
|
||
Для построения таблицы использованы следующие параметры:
|
||
R1(T1): 3кОм(25°С)
|
||
Схема включения: A
|
||
Ra: 3кОм
|
||
Напряжения U0/Uref: 5В/5В
|
||
*/
|
||
const uint16_t termo_table[] = {
|
||
3978, 3934, 3877, 3804, 3713, 3602, 3469, 3313,
|
||
3136, 2939, 2726, 2503, 2275, 2048, 1828, 1618,
|
||
1424, 1246, 1085, 942, 816, 706, 611, 528,
|
||
458, 397
|
||
};
|
||
|
||
// Функция вычисляет значение температуры в десятых долях градусов Цельсия
|
||
// в зависимости от суммарного значения АЦП.
|
||
int16_t calc_temperature(uint16_t adcsum) {
|
||
uint8_t l = 0;
|
||
uint8_t r = (sizeof(termo_table) / sizeof(termo_table[0])) - 1;
|
||
uint16_t thigh = termo_table[r];
|
||
|
||
// Проверка выхода за пределы и граничных значений
|
||
if (adcsum <= thigh) {
|
||
#ifdef TEMPERATURE_UNDER
|
||
if (adcsum < thigh)
|
||
return TEMPERATURE_UNDER;
|
||
#endif
|
||
return TEMPERATURE_TABLE_STEP * r + TEMPERATURE_TABLE_START;
|
||
}
|
||
uint16_t tlow = termo_table[0];
|
||
if (adcsum >= tlow) {
|
||
#ifdef TEMPERATURE_OVER
|
||
if (adcsum > tlow)
|
||
return TEMPERATURE_OVER;
|
||
#endif
|
||
return TEMPERATURE_TABLE_START;
|
||
}
|
||
|
||
// Двоичный поиск по таблице
|
||
while ((r - l) > 1) {
|
||
uint8_t m = (l + r) >> 1;
|
||
uint16_t mid = termo_table[m];
|
||
if (adcsum > mid) {
|
||
r = m;
|
||
} else {
|
||
l = m;
|
||
}
|
||
}
|
||
uint16_t vl = termo_table[l];
|
||
if (adcsum >= vl) {
|
||
return l * TEMPERATURE_TABLE_STEP + TEMPERATURE_TABLE_START;
|
||
}
|
||
uint16_t vr = termo_table[r];
|
||
uint16_t vd = vl - vr;
|
||
int16_t res = TEMPERATURE_TABLE_START + r * TEMPERATURE_TABLE_STEP;
|
||
if (vd) {
|
||
// Линейная интерполяция
|
||
res -= ((TEMPERATURE_TABLE_STEP * (int32_t)(adcsum - vr) + (vd >> 1)) / vd);
|
||
}
|
||
return res;
|
||
}
|