From 83fc0df742ed5c98b600cb303eebc3e2a34c18ad Mon Sep 17 00:00:00 2001 From: cfif Date: Wed, 1 Apr 2026 11:37:59 +0300 Subject: [PATCH] Init --- APP/inc/ADC_Temp.h | 20 ++++- APP/main.c | 98 ++++++++++----------- APP/src/ADC_Temp.c | 215 +++++++++++++++++++++++++-------------------- 3 files changed, 186 insertions(+), 147 deletions(-) diff --git a/APP/inc/ADC_Temp.h b/APP/inc/ADC_Temp.h index 2dafcca..332a2ec 100644 --- a/APP/inc/ADC_Temp.h +++ b/APP/inc/ADC_Temp.h @@ -6,6 +6,7 @@ #define MDF_ADC_TEMP_KST45_14_2_H #include +#include "stdbool.h" // Типы таблиц NTC typedef enum { @@ -33,7 +34,7 @@ typedef enum { #define TABLE_SIZE_INCAR 38 #define TABLE_SIZE_LOOKUP 4096 -// Предварительно вычисленная таблица для быстрого доступа +// Предварительно вычисленная таблица для быстрого доступа для каждой таблицы typedef struct { uint16_t adc_value; // Значение АЦП int16_t temp_c; // Температура в °C * 10 (для фиксированной точки) @@ -50,10 +51,25 @@ typedef struct { uint16_t table_size; // Размер таблицы } ntc_config_t; +// Структура для хранения таблиц быстрого доступа для каждой конфигурации +typedef struct { + adc_temp_lookup kst45[TABLE_SIZE_LOOKUP]; + adc_temp_lookup incar[TABLE_SIZE_LOOKUP]; + bool kst45_initialized; + bool incar_initialized; + float kst45_r1; + float incar_r1; +} fast_lookup_tables_t; + +// Глобальная структура для доступа к таблицам +extern fast_lookup_tables_t g_fast_tables; + // Функции инициализации и конфигурации void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg); +void init_both_tables(float r1_kst45, float r1_incar, eAlg use_alg); void set_active_config(eNtcTable table_type, float r1); const ntc_config_t* get_active_config(void); +const fast_lookup_tables_t* get_fast_tables(void); // Основные функции получения температуры float get_temperature_from_adc(uint16_t adc_value, eAlg alg); @@ -63,8 +79,10 @@ float get_resistance_from_adc_with_table(uint16_t adc_value, eNtcTable table_typ // Быстрые функции с использованием предварительно вычисленной таблицы int16_t get_temperature_log_fast(uint16_t adc_value); +int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_type); int16_t get_temperature_linear_fast(uint16_t adc_value); float get_resistance_log_fast(int16_t temperature_c10); +float get_resistance_log_fast_for_table(int16_t temperature_c10, eNtcTable table_type); float get_resistance_fast_simple(int16_t temperature_c10); #endif //MDF_ADC_TEMP_KST45_14_2_H \ No newline at end of file diff --git a/APP/main.c b/APP/main.c index aa2bd2c..343a2c5 100644 --- a/APP/main.c +++ b/APP/main.c @@ -1,67 +1,63 @@ #include #include "ADC_Temp.h" -extern adc_temp_lookup fast_lookup[TABLE_SIZE_LOOKUP]; - int main() { + // Инициализируем обе таблицы одновременно с разными значениями R1 + init_both_tables(3300.0f, // R1 для KST45 + 20000.0f, // R1 для INCAR + ALG_STEINHART); + uint16_t adc_value = 1980; - printf("\n-----------TABLE_KST45------------------\n"); + printf("\n=== Работа с обеими таблицами одновременно ===\n"); -// Инициализация с таблицей KST45 и R1=3300 Ом - init_fast_lookup_table(TABLE_KST45, 3300.0f, ALG_STEINHART); -// Получение температуры - float temp = get_temperature_from_adc(adc_value, ALG_STEINHART); - int16_t temp_fast = get_temperature_log_fast(adc_value); - printf("ADC: %u, temp_fast: %.1f °C\n", adc_value, temp_fast / 10.0f); + // Получаем температуру для KST45 + int16_t temp_kst45 = get_temperature_log_fast_for_table(adc_value, TABLE_KST45); + printf("KST45: ADC=%u, Temp=%.1f °C\n", adc_value, temp_kst45 / 10.0f); + // Получаем температуру для INCAR + int16_t temp_incar = get_temperature_log_fast_for_table(adc_value, TABLE_INCAR); + printf("INCAR: ADC=%u, Temp=%.1f °C\n", adc_value, temp_incar / 10.0f); - // Пример доступа к таблице - printf("\nПример данных из таблицы быстрого поиска:\n"); - for(int i = TABLE_SIZE_LOOKUP - 1; i > TABLE_SIZE_LOOKUP - 5; i--) { - printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", - fast_lookup[i].adc_value, - fast_lookup[i].temp_c / 10.0f, - fast_lookup[i].resistance_ohm); + // Можно переключать активную конфигурацию + printf("\n=== Переключение активной конфигурации ===\n"); + + set_active_config(TABLE_KST45, 3300.0f); + int16_t temp_active1 = get_temperature_log_fast(adc_value); + printf("Активная (KST45): Temp=%.1f °C\n", temp_active1 / 10.0f); + + set_active_config(TABLE_INCAR, 20000.0f); + int16_t temp_active2 = get_temperature_log_fast(adc_value); + printf("Активная (INCAR): Temp=%.1f °C\n", temp_active2 / 10.0f); + + // Получаем доступ к таблицам для отладки + const fast_lookup_tables_t* tables = get_fast_tables(); + + printf("\n=== Пример данных из таблиц быстрого поиска ===\n"); + printf("KST45 таблица (первые 3 записи):\n"); + for(int i = 0; i < 3; i++) { + printf(" ADC: %u, Temp: %.1f °C, R: %.2f Ω\n", + tables->kst45[i].adc_value, + tables->kst45[i].temp_c / 10.0f, + tables->kst45[i].resistance_ohm); } - // Пример доступа к таблице - printf("\nПример данных из таблицы быстрого поиска:\n"); - for(int i = 0; i < 5; i++) { - printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", - fast_lookup[i].adc_value, - fast_lookup[i].temp_c / 10.0f, - fast_lookup[i].resistance_ohm); - } - - - - printf("\n-----------INCAR------------------\n"); -// Смена конфигурации на INCAR с R1=20000 Ом -// set_active_config(TABLE_INCAR, 2000.0f); - init_fast_lookup_table(TABLE_INCAR, 3300.0f, ALG_STEINHART); - - temp_fast = get_temperature_log_fast(adc_value); - printf("ADC: %u, temp_fast: %.1f °C\n", adc_value, temp_fast / 10.0f); - - // Пример доступа к таблице - printf("\nПример данных из таблицы быстрого поиска:\n"); - for(int i = TABLE_SIZE_LOOKUP - 1; i > TABLE_SIZE_LOOKUP - 5; i--) { - printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", - fast_lookup[i].adc_value, - fast_lookup[i].temp_c / 10.0f, - fast_lookup[i].resistance_ohm); - } - - // Пример доступа к таблице - printf("\nПример данных из таблицы быстрого поиска:\n"); - for(int i = 0; i < 5; i++) { - printf("ADC: %u, Temp: %.1f °C, Resistance: %.2f Ω\n", - fast_lookup[i].adc_value, - fast_lookup[i].temp_c / 10.0f, - fast_lookup[i].resistance_ohm); + printf("\nINCAR таблица (первые 3 записи):\n"); + for(int i = 0; i < 3; i++) { + printf(" ADC: %u, Temp: %.1f °C, R: %.2f Ω\n", + tables->incar[i].adc_value, + tables->incar[i].temp_c / 10.0f, + tables->incar[i].resistance_ohm); } + // Пример обратного преобразования (температура -> сопротивление) + printf("\n=== Обратное преобразование ===\n"); + int16_t temp_test = 250; // 25.0 °C + float resistance_kst45 = get_resistance_log_fast_for_table(temp_test, TABLE_KST45); + float resistance_incar = get_resistance_log_fast_for_table(temp_test, TABLE_INCAR); + printf("При %.1f °C:\n", temp_test / 10.0f); + printf(" KST45 сопротивление: %.2f Ω\n", resistance_kst45); + printf(" INCAR сопротивление: %.2f Ω\n", resistance_incar); return 0; } \ No newline at end of file diff --git a/APP/src/ADC_Temp.c b/APP/src/ADC_Temp.c index 6e1812f..e445b92 100644 --- a/APP/src/ADC_Temp.c +++ b/APP/src/ADC_Temp.c @@ -4,6 +4,7 @@ #include "ADC_Temp.h" #include #include +#include // Структура для хранения табличных данных typedef struct { @@ -83,8 +84,13 @@ static const ntc_table_entry ntc_table_incar[] = { {85, 283.0f} }; -// Глобальная таблица быстрого доступа -adc_temp_lookup fast_lookup[TABLE_SIZE_LOOKUP]; +// Глобальная структура для хранения таблиц быстрого доступа +fast_lookup_tables_t g_fast_tables = { + .kst45_initialized = false, + .incar_initialized = false, + .kst45_r1 = 3300.0f, + .incar_r1 = 3300.0f +}; // Активная конфигурация static ntc_config_t active_config = { @@ -123,6 +129,30 @@ static const ntc_table_entry* get_table_by_type(eNtcTable table_type, uint16_t* return table; } +// Функция для получения указателя на таблицу быстрого доступа по типу +static adc_temp_lookup* get_fast_table_by_type(eNtcTable table_type) { + switch(table_type) { + case TABLE_KST45: + return g_fast_tables.kst45; + case TABLE_INCAR: + return g_fast_tables.incar; + default: + return g_fast_tables.kst45; + } +} + +// Функция для получения статуса инициализации таблицы +static bool is_table_initialized(eNtcTable table_type) { + switch(table_type) { + case TABLE_KST45: + return g_fast_tables.kst45_initialized; + case TABLE_INCAR: + return g_fast_tables.incar_initialized; + default: + return false; + } +} + // Функция расчёта сопротивления NTC из значения АЦП static float calculate_resistance(uint16_t adc_value, float r1) { if (adc_value == 0 || adc_value >= (uint16_t) ADC_MAX) { @@ -271,11 +301,19 @@ float get_resistance_from_adc(uint16_t adc_value) { return calculate_resistance(adc_value, active_config.r1); } -// Инициализация таблицы быстрого поиска +// Инициализация таблицы быстрого поиска для конкретной таблицы void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { uint16_t table_size; int16_t start_temp, end_temp; const ntc_table_entry* table = get_table_by_type(table_type, &table_size, &start_temp, &end_temp); + adc_temp_lookup* fast_table = get_fast_table_by_type(table_type); + + // Сохраняем значение R1 для этой таблицы + if (table_type == TABLE_KST45) { + g_fast_tables.kst45_r1 = r1; + } else { + g_fast_tables.incar_r1 = r1; + } // Находим рабочий диапазон АЦП uint16_t min_valid_adc = 0; @@ -284,7 +322,7 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { // Ищем минимальное АЦП, при котором температура >= start_temp for (uint16_t adc = 1; adc < ADC_MAX; adc++) { float resistance = calculate_resistance(adc, r1); - float temp = get_temperature_from_adc_with_table(adc, ALG_STEINHART, table_type, r1); + float temp = get_temperature_from_adc_with_table(adc, use_alg, table_type, r1); if (temp >= start_temp && temp <= end_temp) { min_valid_adc = adc; @@ -295,7 +333,7 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { // Ищем максимальное АЦП, при котором температура <= end_temp for (uint16_t adc = (uint16_t)(ADC_MAX - 1); adc > 0; adc--) { float resistance = calculate_resistance(adc, r1); - float temp = get_temperature_from_adc_with_table(adc, ALG_STEINHART, table_type, r1); + float temp = get_temperature_from_adc_with_table(adc, use_alg, table_type, r1); if (temp >= start_temp && temp <= end_temp) { max_valid_adc = adc; @@ -319,14 +357,24 @@ void init_fast_lookup_table(eNtcTable table_type, float r1, eAlg use_alg) { if (temp < start_temp) temp = (float)start_temp; if (temp > end_temp) temp = (float)end_temp; - fast_lookup[i].adc_value = adc; - fast_lookup[i].temp_c = (int16_t)(temp * 10.0f); - fast_lookup[i].resistance_ohm = resistance; - fast_lookup[i].table_type = table_type; + fast_table[i].adc_value = adc; + fast_table[i].temp_c = (int16_t)(temp * 10.0f); + fast_table[i].resistance_ohm = resistance; + fast_table[i].table_type = table_type; } - // Обновляем активную конфигурацию - set_active_config(table_type, r1); + // Устанавливаем флаг инициализации + if (table_type == TABLE_KST45) { + g_fast_tables.kst45_initialized = true; + } else { + g_fast_tables.incar_initialized = true; + } +} + +// Инициализация обеих таблиц +void init_both_tables(float r1_kst45, float r1_incar, eAlg use_alg) { + init_fast_lookup_table(TABLE_KST45, r1_kst45, use_alg); + init_fast_lookup_table(TABLE_INCAR, r1_incar, use_alg); } // Установка активной конфигурации @@ -344,14 +392,33 @@ const ntc_config_t* get_active_config(void) { return &active_config; } -// Быстрые функции с использованием предварительно вычисленной таблицы +// Получение таблиц быстрого доступа +const fast_lookup_tables_t* get_fast_tables(void) { + return &g_fast_tables; +} + +// Быстрые функции с использованием активной таблицы int16_t get_temperature_log_fast(uint16_t adc_value) { - // Защита от выхода за границы - if (adc_value >= fast_lookup[TABLE_SIZE_LOOKUP - 1].adc_value) { - return fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c; + return get_temperature_log_fast_for_table(adc_value, active_config.table_type); +} + +// Быстрая функция для конкретной таблицы +int16_t get_temperature_log_fast_for_table(uint16_t adc_value, eNtcTable table_type) { + if (!is_table_initialized(table_type)) { + // Если таблица не инициализирована, используем обычный расчет + float temp = get_temperature_from_adc_with_table(adc_value, ALG_STEINHART, table_type, + (table_type == TABLE_KST45) ? g_fast_tables.kst45_r1 : g_fast_tables.incar_r1); + return (int16_t)(temp * 10.0f); } - if (adc_value <= fast_lookup[0].adc_value) { - return fast_lookup[0].temp_c; + + adc_temp_lookup* fast_table = get_fast_table_by_type(table_type); + + // Защита от выхода за границы + if (adc_value >= fast_table[TABLE_SIZE_LOOKUP - 1].adc_value) { + return fast_table[TABLE_SIZE_LOOKUP - 1].temp_c; + } + if (adc_value <= fast_table[0].adc_value) { + return fast_table[0].temp_c; } // Бинарный поиск интервала @@ -361,18 +428,18 @@ int16_t get_temperature_log_fast(uint16_t adc_value) { while (left <= right) { int mid = left + (right - left) / 2; - if (fast_lookup[mid].adc_value <= adc_value && - (mid == TABLE_SIZE_LOOKUP - 1 || adc_value < fast_lookup[mid + 1].adc_value)) { + if (fast_table[mid].adc_value <= adc_value && + (mid == TABLE_SIZE_LOOKUP - 1 || adc_value < fast_table[mid + 1].adc_value)) { // Нашли интервал if (mid == TABLE_SIZE_LOOKUP - 1) { - return fast_lookup[mid].temp_c; + return fast_table[mid].temp_c; } // Линейная интерполяция - uint16_t adc1 = fast_lookup[mid].adc_value; - uint16_t adc2 = fast_lookup[mid + 1].adc_value; - int16_t temp1 = fast_lookup[mid].temp_c; - int16_t temp2 = fast_lookup[mid + 1].temp_c; + uint16_t adc1 = fast_table[mid].adc_value; + uint16_t adc2 = fast_table[mid + 1].adc_value; + int16_t temp1 = fast_table[mid].temp_c; + int16_t temp2 = fast_table[mid + 1].temp_c; if (adc2 == adc1) { return temp1; @@ -381,49 +448,40 @@ int16_t get_temperature_log_fast(uint16_t adc_value) { return temp1 + ((int32_t) (temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); } - if (adc_value < fast_lookup[mid].adc_value) { + if (adc_value < fast_table[mid].adc_value) { right = mid - 1; } else { left = mid + 1; } } - return fast_lookup[0].temp_c; + return fast_table[0].temp_c; } // Альтернативная простая версия int16_t get_temperature_linear_fast(uint16_t adc_value) { - // Находим интервал - uint16_t i = 0; - while (i < TABLE_SIZE_LOOKUP - 1 && adc_value > fast_lookup[i + 1].adc_value) { - i++; - } - - // Линейная интерполяция - if (i >= TABLE_SIZE_LOOKUP - 1) { - return fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c; - } - - uint16_t adc1 = fast_lookup[i].adc_value; - uint16_t adc2 = fast_lookup[i + 1].adc_value; - int16_t temp1 = fast_lookup[i].temp_c; - int16_t temp2 = fast_lookup[i + 1].temp_c; - - if (adc2 == adc1) { - return temp1; - } - - return temp1 + ((int32_t) (temp2 - temp1) * (adc_value - adc1)) / (adc2 - adc1); + return get_temperature_log_fast_for_table(adc_value, active_config.table_type); } // Функция для получения сопротивления из температуры (обратное преобразование) float get_resistance_log_fast(int16_t temperature_c10) { - // Защита от выхода за границы - if (temperature_c10 >= fast_lookup[0].temp_c) { - return fast_lookup[0].resistance_ohm; + return get_resistance_log_fast_for_table(temperature_c10, active_config.table_type); +} + +// Функция для получения сопротивления из температуры для конкретной таблицы +float get_resistance_log_fast_for_table(int16_t temperature_c10, eNtcTable table_type) { + if (!is_table_initialized(table_type)) { + return 0.0f; } - if (temperature_c10 <= fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c) { - return fast_lookup[TABLE_SIZE_LOOKUP - 1].resistance_ohm; + + adc_temp_lookup* fast_table = get_fast_table_by_type(table_type); + + // Защита от выхода за границы + if (temperature_c10 >= fast_table[0].temp_c) { + return fast_table[0].resistance_ohm; + } + if (temperature_c10 <= fast_table[TABLE_SIZE_LOOKUP - 1].temp_c) { + return fast_table[TABLE_SIZE_LOOKUP - 1].resistance_ohm; } // Бинарный поиск интервала по температуре @@ -433,13 +491,13 @@ float get_resistance_log_fast(int16_t temperature_c10) { while (left <= right) { int mid = left + (right - left) / 2; - if (temperature_c10 <= fast_lookup[mid].temp_c && - temperature_c10 >= fast_lookup[mid + 1].temp_c) { + if (temperature_c10 <= fast_table[mid].temp_c && + temperature_c10 >= fast_table[mid + 1].temp_c) { // Нашли интервал - int16_t temp_high = fast_lookup[mid].temp_c; - int16_t temp_low = fast_lookup[mid + 1].temp_c; - float res_high = fast_lookup[mid].resistance_ohm; - float res_low = fast_lookup[mid + 1].resistance_ohm; + int16_t temp_high = fast_table[mid].temp_c; + int16_t temp_low = fast_table[mid + 1].temp_c; + float res_high = fast_table[mid].resistance_ohm; + float res_low = fast_table[mid + 1].resistance_ohm; if (temp_high == temp_low) { return res_high; @@ -454,50 +512,17 @@ float get_resistance_log_fast(int16_t temperature_c10) { return expf(log_res); } - if (temperature_c10 > fast_lookup[mid].temp_c) { + if (temperature_c10 > fast_table[mid].temp_c) { right = mid - 1; } else { left = mid + 1; } } - return fast_lookup[TABLE_SIZE_LOOKUP - 1].resistance_ohm; + return fast_table[TABLE_SIZE_LOOKUP - 1].resistance_ohm; } // Упрощенная версия с линейным поиском float get_resistance_fast_simple(int16_t temperature_c10) { - // Защита от выхода за границы - if (temperature_c10 >= fast_lookup[0].temp_c) { - return fast_lookup[0].resistance_ohm; - } - if (temperature_c10 <= fast_lookup[TABLE_SIZE_LOOKUP - 1].temp_c) { - return fast_lookup[TABLE_SIZE_LOOKUP - 1].resistance_ohm; - } - - // Линейный поиск интервала - for (uint16_t i = 0; i < TABLE_SIZE_LOOKUP - 1; i++) { - if (temperature_c10 <= fast_lookup[i].temp_c && - temperature_c10 >= fast_lookup[i + 1].temp_c) { - - int16_t temp_high = fast_lookup[i].temp_c; - int16_t temp_low = fast_lookup[i + 1].temp_c; - float res_high = fast_lookup[i].resistance_ohm; - float res_low = fast_lookup[i + 1].resistance_ohm; - - if (temp_high == temp_low) { - return res_high; - } - - // Логарифмическая интерполяция - float log_res_high = logf(res_high); - float log_res_low = logf(res_low); - float log_res = log_res_high + (log_res_low - log_res_high) * - (float)(temp_high - temperature_c10) / (float)(temp_high - temp_low); - - return expf(log_res); - } - } - - return fast_lookup[TABLE_SIZE_LOOKUP - 1].resistance_ohm; -} - + return get_resistance_log_fast_for_table(temperature_c10, active_config.table_type); +} \ No newline at end of file