#include #include "ADC_Temp.h" // Упрощенная структура для хранения записи таблицы typedef struct { uint16_t adc_value; // Значение АЦП int16_t temp_c; // Температура в °C * 10 float resistance_ohm; // Сопротивление в Ом } adc_temp_lookup_entry_t; // Функция для сохранения температур в одну строку через пробел (все значения) void save_temperature_int_one_line(const char* filename, const adc_temp_lookup* table, const char* table_name) { FILE* file = fopen(filename, "w"); if (file == NULL) { printf("Ошибка: не удалось создать файл %s\n", filename); return; } fprintf(file, "# Температуры для таблицы %s (одна строка, через пробел)\n", table_name); fprintf(file, "# VCC=%.2fV, VREF=%.2fV\n", VCC_DIVIDER_MV / 1000.0f, VREF_MV / 1000.0f); fprintf(file, "# Всего значений: %d\n", TABLE_SIZE_LOOKUP); fprintf(file, "# Температура в °C * 10 (целые числа)\n\n"); for (int i = 0; i < TABLE_SIZE_LOOKUP; i++) { if (i > 0) fprintf(file, " "); fprintf(file, "%d", table[i].temp_c); } fprintf(file, "\n"); fclose(file); printf("Температуры (int one-line) для '%s' сохранены в файл: %s\n", table_name, filename); } // Функция для сохранения таблицы в C файл в виде статического массива void save_table_to_c_file(const char* filename, const adc_temp_lookup* table, const char* table_name, const char* array_name) { FILE* file = fopen(filename, "w"); if (file == NULL) { printf("Ошибка: не удалось создать файл %s\n", filename); return; } // Заголовок файла fprintf(file, "//\n"); fprintf(file, "// Автоматически сгенерированный файл таблицы быстрого поиска: %s\n", table_name); fprintf(file, "// VCC делителя = %.2f V\n", VCC_DIVIDER_MV / 1000.0f); fprintf(file, "// VREF АЦП = %.2f V\n", VREF_MV / 1000.0f); fprintf(file, "// Сопротивление R1 = %.0f Ом\n", (table_name[0] == 'D' && table_name[1] == 'U') ? g_fast_tables.duct_r1 : (table_name[0] == 'I') ? g_fast_tables.incar_r1 : g_fast_tables.ambient_r1); fprintf(file, "// Всего записей: %d\n", TABLE_SIZE_LOOKUP); fprintf(file, "//\n\n"); fprintf(file, "#include \n\n"); // Структура для элемента таблицы fprintf(file, "// Структура для хранения записи таблицы\n"); fprintf(file, "typedef struct {\n"); fprintf(file, " uint16_t adc_value; // Значение АЦП\n"); fprintf(file, " int16_t temp_c; // Температура в °C * 10\n"); fprintf(file, " float resistance_ohm; // Сопротивление в Ом\n"); fprintf(file, "} adc_temp_lookup_entry_t;\n\n"); // Объявление массива fprintf(file, "static const adc_temp_lookup_entry_t %s[%d] = {\n", array_name, TABLE_SIZE_LOOKUP); // Вывод данных - по 4 элемента в строке для компактности for (int i = 0; i < TABLE_SIZE_LOOKUP; i++) { if (i % 4 == 0) { fprintf(file, " "); } // Округляем сопротивление до 2 знаков после запятой fprintf(file, "{%u, %d, %.2ff}", table[i].adc_value, table[i].temp_c, table[i].resistance_ohm); if (i < TABLE_SIZE_LOOKUP - 1) { fprintf(file, ", "); } if ((i + 1) % 4 == 0) { fprintf(file, "\n"); } } // Завершаем массив if (TABLE_SIZE_LOOKUP % 4 != 0) { fprintf(file, "\n"); } fprintf(file, "};\n\n"); // Добавляем функцию для быстрого доступа по ADC fprintf(file, "// Быстрый поиск температуры по ADC (прямая индексация)\n"); fprintf(file, "static inline int16_t %s_get_temp(uint16_t adc_value) {\n", array_name); fprintf(file, " if (adc_value >= %d) return %s[%d].temp_c;\n", TABLE_SIZE_LOOKUP, array_name, TABLE_SIZE_LOOKUP - 1); fprintf(file, " return %s[adc_value].temp_c;\n", array_name); fprintf(file, "}\n\n"); fprintf(file, "// Быстрый поиск сопротивления по ADC (прямая индексация)\n"); fprintf(file, "static inline float %s_get_resistance(uint16_t adc_value) {\n", array_name); fprintf(file, " if (adc_value >= %d) return %s[%d].resistance_ohm;\n", TABLE_SIZE_LOOKUP, array_name, TABLE_SIZE_LOOKUP - 1); fprintf(file, " return %s[adc_value].resistance_ohm;\n", array_name); fprintf(file, "}\n\n"); // Добавляем функцию для обратного поиска (температура -> сопротивление) fprintf(file, "// Поиск сопротивления по температуре (бинарный поиск)\n"); fprintf(file, "static inline float %s_get_resistance_by_temp(int16_t temp_c10) {\n", array_name); fprintf(file, " if (temp_c10 >= %s[0].temp_c) return %s[0].resistance_ohm;\n", array_name, array_name); fprintf(file, " if (temp_c10 <= %s[%d].temp_c) return %s[%d].resistance_ohm;\n", array_name, TABLE_SIZE_LOOKUP - 1, array_name, TABLE_SIZE_LOOKUP - 1); fprintf(file, " \n"); fprintf(file, " // Бинарный поиск\n"); fprintf(file, " int left = 0, right = %d;\n", TABLE_SIZE_LOOKUP - 1); fprintf(file, " while (left <= right) {\n"); fprintf(file, " int mid = left + (right - left) / 2;\n"); fprintf(file, " if (temp_c10 >= %s[mid].temp_c && temp_c10 <= %s[mid + 1].temp_c) {\n", array_name, array_name); fprintf(file, " // Нашли интервал, интерполируем в логарифмическом масштабе\n"); fprintf(file, " int16_t t_high = %s[mid].temp_c;\n", array_name); fprintf(file, " int16_t t_low = %s[mid + 1].temp_c;\n", array_name); fprintf(file, " float r_high = %s[mid].resistance_ohm;\n", array_name); fprintf(file, " float r_low = %s[mid + 1].resistance_ohm;\n", array_name); fprintf(file, " \n"); fprintf(file, " if (t_high == t_low) return r_high;\n"); fprintf(file, " \n"); fprintf(file, " float log_r_high = logf(r_high);\n"); fprintf(file, " float log_r_low = logf(r_low);\n"); fprintf(file, " float log_r = log_r_high + (log_r_low - log_r_high) * \n"); fprintf(file, " (float)(t_high - temp_c10) / (float)(t_high - t_low);\n"); fprintf(file, " return expf(log_r);\n"); fprintf(file, " }\n"); fprintf(file, " \n"); fprintf(file, " if (temp_c10 > %s[mid].temp_c) {\n", array_name); fprintf(file, " right = mid - 1;\n"); fprintf(file, " } else {\n"); fprintf(file, " left = mid + 1;\n"); fprintf(file, " }\n"); fprintf(file, " }\n"); fprintf(file, " return %s[%d].resistance_ohm;\n", array_name, TABLE_SIZE_LOOKUP - 1); fprintf(file, "}\n"); fclose(file); printf("Таблица '%s' сохранена в файл: %s\n", table_name, filename); } // Функция для сохранения таблицы в CSV формате (для Excel) void save_table_to_csv(const char* filename, const adc_temp_lookup* table, const char* table_name) { FILE* file = fopen(filename, "w"); if (file == NULL) { printf("Ошибка: не удалось создать файл %s\n", filename); return; } fprintf(file, "# Таблица быстрого поиска: %s\n", table_name); fprintf(file, "# VCC_DIVIDER = %.2f V, VREF = %.2f V\n", VCC_DIVIDER_MV / 1000.0f, VREF_MV / 1000.0f); fprintf(file, "ADC,Temperature_C,Temperature_x10,Resistance_Ohm\n"); for (int i = 0; i < TABLE_SIZE_LOOKUP; i++) { fprintf(file, "%u,%.1f,%d,%.2f\n", table[i].adc_value, table[i].temp_c / 10.0f, table[i].temp_c, table[i].resistance_ohm); } fclose(file); printf("Таблица '%s' сохранена в CSV файл: %s\n", table_name, filename); } // Функция для сохранения таблицы в TXT формате (для просмотра) void save_table_to_txt(const char* filename, const adc_temp_lookup* table, const char* table_name) { FILE* file = fopen(filename, "w"); if (file == NULL) { printf("Ошибка: не удалось создать файл %s\n", filename); return; } fprintf(file, "=== Таблица быстрого поиска: %s ===\n", table_name); fprintf(file, "VCC делителя = %.2f V\n", VCC_DIVIDER_MV / 1000.0f); fprintf(file, "VREF АЦП = %.2f V\n", VREF_MV / 1000.0f); fprintf(file, "Всего записей: %d\n", TABLE_SIZE_LOOKUP); fprintf(file, "%-8s %-12s %-15s\n", "ADC", "Temp (°C)", "Resistance (Ω)"); fprintf(file, "---------------------------------------------\n"); // Выводим каждые 100 записей для компактности for (int i = 0; i < TABLE_SIZE_LOOKUP; i++) { fprintf(file, "%-8u %-12.1f %-15.2f\n", table[i].adc_value, table[i].temp_c / 10.0f, table[i].resistance_ohm); } fclose(file); printf("Таблица '%s' сохранена в TXT файл: %s\n", table_name, filename); } // Функция для сохранения всех таблиц во всех форматах void save_all_tables_to_files(void) { const fast_lookup_tables_t* tables = get_fast_tables(); printf("\n=== Сохранение таблиц в файлы ===\n"); // Сохраняем DUCT таблицу save_table_to_c_file("duct_table_array.c", tables->duct, "DUCT", "duct_lookup_table"); save_table_to_csv("duct_table.csv", tables->duct, "DUCT"); save_table_to_txt("duct_table.txt", tables->duct, "DUCT"); save_temperature_int_one_line("duct_temperatures.txt", tables->duct, "DUCT"); // Сохраняем INCAR таблицу save_table_to_c_file("incar_table_array.c", tables->incar, "INCAR", "incar_lookup_table"); save_table_to_csv("incar_table.csv", tables->incar, "INCAR"); save_table_to_txt("incar_table.txt", tables->incar, "INCAR"); save_temperature_int_one_line("incar_temperatures.txt", tables->incar, "INCAR"); // Сохраняем AMBIENT таблицу save_table_to_c_file("ambient_table_array.c", tables->ambient, "AMBIENT", "ambient_lookup_table"); save_table_to_csv("ambient_table.csv", tables->ambient, "AMBIENT"); save_table_to_txt("ambient_table.txt", tables->ambient, "AMBIENT"); save_temperature_int_one_line("ambient_temperatures.txt", tables->ambient, "AMBIENT"); printf("\nВсе таблицы успешно сохранены!\n"); } int main() { printf("=== Генерация таблиц быстрого поиска для NTC термисторов ===\n"); printf("Конфигурация:\n"); printf(" VCC делителя = %.2f V\n", VCC_DIVIDER_MV / 1000.0f); printf(" VREF АЦП = %.2f V\n", VREF_MV / 1000.0f); printf(" ADC_MAX = %.0f\n", ADC_MAX); // Инициализируем все три таблицы printf("\n=== Инициализация таблиц ===\n"); init_all_tables(3000.0f, // R1 для DUCT (KST45) - 3kΩ 20000.0f, // R1 для INCAR - 20kΩ 20000.0f, // R1 для AMBIENT (NTC 10k) - 20kΩ ALG_STEINHART); printf("Таблицы успешно инициализированы\n"); // Сохраняем таблицы в файлы save_all_tables_to_files(); printf("\n=== Готово ===\n"); printf("Сгенерированы файлы:\n"); printf(" - duct_table_array.c, incar_table_array.c, ambient_table_array.c (статический массив)\n"); printf(" - duct_table.csv, incar_table.csv, ambient_table.csv (для Excel)\n"); printf(" - duct_table.txt, incar_table.txt, ambient_table.txt (для просмотра)\n"); printf(" - duct_temperatures.txt, incar_temperatures.txt, ambient_temperatures.txt (температуры в одну строку)\n"); return 0; }