#include "at32f403a_407.h" #include "modbus_params.h" #include "io.h" #include "uptime.h" #include "rtc.h" #include "digital_input.h" #include "digital_output.h" #include "log.h" #include "settings_api.h" #include "common_config.h" #include "swap.h" #include mb_param_t mb_param[MB_PARAM_MAX]; uint32_t rtc_sinhro; // Пароль для установки системных настроек uint16_t psw; bool psw_ok = false; uint8_t fw_version[8]; uint16_t save_sys_cmd = 0; // Команда сохранения системных настроек uint16_t system_cmd = 0; // Команда управления контроллером uint64_t value_64 = 0; uint8_t value_8 = 0; uint8_t arch_channel = 0; void get_time(uint8_t* buf, uint8_t size); void get_din_mode(uint8_t* buf, uint8_t size); void get_log_entries_number(uint8_t* buf, uint8_t size); void get_arch_ch_1(uint8_t* buf, uint8_t size); void get_arch_ch_2(uint8_t* buf, uint8_t size); void get_arch_ch_3(uint8_t* buf, uint8_t size); void get_arch_ch_4(uint8_t* buf, uint8_t size); void get_arch_ch_5(uint8_t* buf, uint8_t size); void get_arch_ch_6(uint8_t* buf, uint8_t size); void get_arch_ch_7(uint8_t* buf, uint8_t size); void get_arch_ch_8(uint8_t* buf, uint8_t size); void (*get_ch_entries_number[8])(uint8_t* buf, uint8_t size) = { get_arch_ch_1, get_arch_ch_2, get_arch_ch_3, get_arch_ch_4, get_arch_ch_5, get_arch_ch_6, get_arch_ch_7, get_arch_ch_8, }; void get_rtc(uint8_t* buf, uint8_t size); // void mb_init_params(void) { uint16_t index = 0; uint16_t addr = 0; mb_param[index].reg = 0x0100; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&di_state_bit; // Текущее состояние входов mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Счетчики импульсов. Регистры 0x0102 - 0x0111 addr = 0x0102; for (int i = 0; i < DI_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 2; mb_param[index].param = (uint8_t*)&di_cnt[i]; // Счетчик ипульсов mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr += 2; index++; } // Режим работы входов mb_param[index].reg = 0x0120; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&settings.di_mode_bits; mb_param[index].set = mb_set_din_mode; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Нормальное состояние входов mb_param[index].reg = 0x0122; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&settings.di_norm_state_bits; mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Время антидребезга addr = 0x0124; for (int i = 0; i < DI_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&settings.di_debounce[i]; mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // Текущее состояние датчиков нагрузки mb_param[index].reg = 0x0130; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&di_load_state_bit; mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Слово достоверности датчиков нагрузки [1 - показания достоверны, 0 - нет] mb_param[index].reg = 0x0131; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&di_credibility_state_bit; mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Текущее состояние выходов mb_param[index].reg = 0x0200; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_state_bit; mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Режим работы выходов mb_param[index].reg = 0x0202; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_mode_bit; mb_param[index].set = mb_set_do_mode; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Состояние выходов в безопасном режиме mb_param[index].reg = 0x0203; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&settings.do_save_bits; mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Заполнение PWM. Регистры 0x0210 - 0x0217 addr = 0x0210; for (int i = 0; i < DO_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_pwm[i]; // Счетчик ипульсов mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // Заполнение PWM в безопасном режиме. Регистры 0x0220 - 0x0227 addr = 0x0220; for (int i = 0; i < DO_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_pwm_save[i]; // Счетчик ипульсов mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // Период PWM. Регистры 0x0220 - 0x0227 addr = 0x0230; for (int i = 0; i < DO_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_pwm_period[i]; // Счетчик ипульсов mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // Период PWM. Регистры 0x0220 - 0x0227 addr = 0x0240; for (int i = 0; i < DO_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&output_pwm_period_save[i]; // Счетчик ипульсов mb_param[index].set = mb_set_do; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // ---------------------------------------------------------------------- // // Управление контроллером. Разные параметры. // ---------------------------------------------------------------------- // // Управление контроллером mb_param[index].reg = 0x0800; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&system_cmd; // mb_param[index].set = mb_control; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // uptime mb_param[index].reg = 0x0801; mb_param[index].size = 2; mb_param[index].param = (uint8_t*)&uptime; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // RTC mb_param[index].reg = 0x0803; mb_param[index].size = 4; mb_param[index].param = (uint8_t*)&value_64; // mb_param[index].set = mb_set_rtc; mb_param[index].get = get_rtc; mb_param[index].check_handler = mb_check_dummy; index++; // ---------------------------------------------------------------------- // // Журналы/рахивы // ---------------------------------------------------------------------- // // Емкость журнала (максимальная) mb_param[index].reg = 0x0900; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&log_entries_capacity; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Текущее количество записей в журнале mb_param[index].reg = 0x0901; mb_param[index].size = 1; mb_param[index].param = NULL; // mb_param[index].set = NULL; mb_param[index].get = get_log_entries_number; mb_param[index].check_handler = mb_check_dummy; index++; // Емкость архива (максимальная) mb_param[index].reg = 0x0902; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&archive_entries_capacity; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Текущее количество записей в архиве по каждому каналу addr = 0x0903; for (int i = 0; i < ARCH_CH_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = NULL; mb_param[index].set = NULL; mb_param[index].get = get_ch_entries_number[i]; mb_param[index].check_handler = mb_check_dummy; addr++; index++; } // Период архива. Регистры 0x0904 - 0x090B addr = 0x090B; for (int i = 0; i < ARCH_CH_NUMBER; i++) { mb_param[index].reg = addr; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&settings.period_archive[i]; // Счетчик ипульсов mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_archiv_per; addr++; index++; } // ---------------------------------------------------------------------- // // Системные настройки // ---------------------------------------------------------------------- // // Код модели (только чтение). Определяется прошивкой. mb_param[index].reg = 0x0080; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&model_code; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Дата производства Unix формат (чтение/запись по паролю) mb_param[index].reg = 0x0081; mb_param[index].size = 2; mb_param[index].param = (uint8_t*)&temp_sys_settings.prod_date; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Серийный номер (чтение/запись по паролю). mb_param[index].reg = 0x0083; mb_param[index].size = 2; mb_param[index].param = (uint8_t*)&temp_sys_settings.sn; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Версия ПО (только чтение). memcpy(&fw_version, FW_VERSION, 8); mb_param[index].reg = 0x0085; mb_param[index].size = 4; mb_param[index].param = (uint8_t*)&fw_version; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Статус тестирования (чтение/запись по паролю). mb_param[index].reg = 0x0089; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&temp_sys_settings.test_state; // mb_param[index].set = NULL; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Пароль mb_param[index].reg = 0x008A; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&psw; // mb_param[index].set = mb_password; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; // Команда на сохранение системных настроек mb_param[index].reg = 0x008B; mb_param[index].size = 1; mb_param[index].param = (uint8_t*)&save_sys_cmd; // mb_param[index].set = mb_sys_settings_save; mb_param[index].get = NULL; mb_param[index].check_handler = mb_check_dummy; index++; } // Возвращает размер параметра в регистрах bool mb_find_param(uint16_t reg, uint16_t *index, uint16_t *size) { for (uint16_t i = 0; i < MB_PARAM_MAX; i++) { if (mb_param[i].reg == reg) { *index = i; *size = mb_param[i].size; return true; } } return false; } // mb_delay_action_t mb_set_param(uint8_t *buf, uint16_t index) { uint8_t *ptr = mb_param[index].param; // Если параметр только для чтения if (mb_param[index].check_handler == NULL) return MB_NO_ACTION; for (uint16_t i = 0; i < 2*mb_param[index].size; i++) { *ptr = buf[2*mb_param[index].size - 1 - i]; ptr++; } /* if (mb_param[index].check_handler != NULL) mb_param[index].check_handler(); */ mb_param[index].check_handler(); if (mb_param[index].set != NULL) return mb_param[index].set(); else return MB_NO_ACTION; /* if (mb_param[index].f_activity) return mb_param[index].set_handler(); else return MB_NO_ACTION; */ } // void mb_get_param(uint8_t *buf, uint16_t index) { uint8_t *ptr; if (mb_param[index].get != NULL) { mb_param[index].get(buf, mb_param[index].size); return; } ptr = mb_param[index].param + 2*mb_param[index].size - 1; for (uint16_t i = 0; i < 2*mb_param[index].size; i++) { *buf = *ptr; buf++; ptr--; } } // -------------------------------------------------------------------------- // // Чтение параметров // -------------------------------------------------------------------------- // #if 0 void get_time(uint8_t* buf, uint8_t size) { uint32_t rtc_unix = RTC_GetUnixTime(); uint8_t *ptr = (uint8_t*)&rtc_unix + 2*size - 1; for (uint16_t i = 0; i < 2*size; i++) { *buf = *ptr; buf++; ptr--; } } #endif // void get_din_mode(uint8_t* buf, uint8_t size) { } // void get_log_entries_number(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_capacity()); memcpy(buf, &capacity, 2); //buf = (uint8_t*)&capacity; } // void get_arch_ch_1(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(0)); memcpy(buf, &capacity, 2); } // void get_arch_ch_2(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(1)); memcpy(buf, &capacity, 2); } // void get_arch_ch_3(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(2)); memcpy(buf, &capacity, 2); } // void get_arch_ch_4(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(3)); memcpy(buf, &capacity, 2); } // void get_arch_ch_5(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(4)); memcpy(buf, &capacity, 2); } // void get_arch_ch_6(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(5)); memcpy(buf, &capacity, 2); } // void get_arch_ch_7(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(6)); memcpy(buf, &capacity, 2); } // void get_arch_ch_8(uint8_t* buf, uint8_t size) { static uint16_t capacity; capacity = swap_uint16(log_arch_capacity(7)); memcpy(buf, &capacity, 2); } // void get_rtc(uint8_t* buf, uint8_t size) { uint64_t rtc = swap_uint64(rtc_get_ms()); memcpy(buf, &rtc, 8); } // -------------------------------------------------------------------------- // // Установка параметров // -------------------------------------------------------------------------- // // mb_delay_action_t mb_set_din_mode(void) { di_set(); return MB_NO_ACTION; } // mb_delay_action_t mb_set_do(void) { do_set_common(); return MB_NO_ACTION; } // mb_delay_action_t mb_set_do_mode(void) { do_set_mode(); return MB_NO_ACTION; } // mb_delay_action_t mb_set_time(void) { TM_RTC_SetDataTimeUnix(rtc_sinhro); return MB_NO_ACTION; } // mb_delay_action_t mb_password(void) { if (psw != MB_PASSWORD) return MB_PAS_ERR; else { if (psw_ok == false) { psw_ok = true; return MB_PAS_OK; } else return MB_NO_ACTION; } } // mb_delay_action_t mb_sys_settings_save(void) { if (save_sys_cmd == 1) return MB_SAVE_SYS_SETTINGS; else return MB_NO_ACTION; } // mb_delay_action_t mb_control(void) { if (system_cmd == MB_COM_SETTINGS_SAVE) return MB_SAVE_SETTINGS; else if (system_cmd == MB_COM_LOG_CLEAR) return MB_LOG_CLEAR; else if ((system_cmd >= (uint8_t)MB_COM_ARCH_CLEAR_1) && (system_cmd <= (uint8_t)MB_COM_ARCH_CLEAR_8)) { arch_channel = system_cmd; return MB_ARCHIVE_CLEAR; } return MB_NO_ACTION; #if 0 if (system_cmd == 1) return MB_SAVE_SETTINGS; else if (system_cmd == 2) return MB_DEF_SETTINGS; else if (system_cmd == 3) return MB_RESET; else if (system_cmd == 4) return MB_PART_DEF_SETTINGS; return MB_NO_ACTION; #endif } // mb_delay_action_t mb_set_rtc(void) { float delta; uint64_t now = rtc_get_ms(); if (now >= value_64) delta = (float)(now - value_64); else delta = (float)(value_64 - now); rtc_set_in_ms((uint32_t)(value_64/1000)); // -------------------------------------------------------------------------- // // EVENT. Перевод времени. log_add_entry(LOG_CLOCK_CHANGE, LOG_EVENT_STATE_OK, 0, delta); return MB_NO_ACTION; } // -------------------------------------------------------------------------- // // Проверка параметров // // -------------------------------------------------------------------------- // // void mb_check_dummy(void) { } // void mb_check_archiv_per(void) { for (uint8_t i = 0; i < ARCH_CH_NUMBER; i++) { if (settings.period_archive[i] > (uint16_t)MAX_ARCHIVE_PERIOD) settings.period_archive[i] = (uint16_t)MAX_ARCHIVE_PERIOD; } }