TelenkovDmitry 5 月之前
父節點
當前提交
bd6dd06542

+ 451 - 448
fw/modules/io/digital_input.c

@@ -1,448 +1,451 @@
-#include "at32f403a_407.h"
-#include "digital_input.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "settings_api.h"
-#include "io_utils.h"
-#include "mux.h"
-#include <stdio.h>
-
-#if defined (MDIO_88)
-
-// Цифровые входы
-// *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
-din_t d_inputs[DI_NUMBER] = {
-    {GPIOB, GPIO_PINS_11, 0, 0, 0, false, false}, // 1   
-    {GPIOB, GPIO_PINS_10, 0, 0, 0, false, false}, // 2
-    {GPIOE, GPIO_PINS_14, 0, 0, 0, false, false}, // 3 перенесли {GPIOB, GPIO_PINS_1,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE1,  0},
-    {GPIOE, GPIO_PINS_15, 0, 0, 0, false, false}, // 4 перенесли {GPIOB, GPIO_PINS_0,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE0,  0},
-    {GPIOA, GPIO_PINS_3,  0, 0, 0, false, false}, // 5
-    {GPIOA, GPIO_PINS_2,  0, 0, 0, false, false}, // 6
-    {GPIOA, GPIO_PINS_1,  0, 0, 0, false, false}, // 7
-    {GPIOA, GPIO_PINS_0,  0, 0, 0, false, false}  // 8
-};
-
-// Датчики обрыва нагрузки
-simple_gpio_t di_load[DI_NUMBER] = {
-    {GPIOD, GPIO_PINS_0},
-    {GPIOD, GPIO_PINS_1},
-    {GPIOC, GPIO_PINS_13},
-    {GPIOC, GPIO_PINS_0},
-    {GPIOC, GPIO_PINS_10},
-    {GPIOD, GPIO_PINS_4},
-    {GPIOE, GPIO_PINS_4},
-    {GPIOC, GPIO_PINS_3}
-};
-
-// -------------------------------------------------------------------------- //
-// Текущие параметры
-
-uint32_t di_cnt[DI_NUMBER];         // счетчики входов
-
-uint16_t di_state[DI_NUMBER];       // состояние входов
-uint16_t di_state_bit;
-
-uint16_t di_load_state[DO_NUMBER];  // состояние датчиков обрыва нагрузки
-uint16_t di_load_state_bit;
-
-uint16_t di_credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
-uint16_t di_credibility_state_bit;         // достоверность состояния датчиков нагрузки
-
-
-// Настройка периферии дискретных входов (GPIO, EXTI, TIM).
-// Настройка датчиков обрыва нагрузки (GPIO).
-// Вызывается единственный раз при старте контроллера.
-// Периферия настраивается однозначно и только один раз.
-void di_init(void)
-{
-    // Входы
-    for (int i = 0; i < DI_NUMBER; i++) {
-        di_base_init(&d_inputs[i]);
-        di_load_sens_init(&di_load[i]);
-    }
-    
-    // EXTI
-    di_exti_init();
-    
-    // Таймер для антидребезга
-    di_tim_init();
-}
-
-
-// Настройка GPIO дискретных входов
-void di_base_init(din_t *input)
-{
-    gpio_init_type gpio_init_struct;
-
-    gpio_default_para_init(&gpio_init_struct);
-        
-    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
-    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
-    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-    gpio_init_struct.gpio_pins           = input->pin;
-    gpio_init(input->port, &gpio_init_struct);
-}
-
-
-// Настройка EXTI дискретных входов
-void di_exti_init(void)
-{
-    exint_init_type exint_init_struct;
-    
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE11); // 11
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE10); // 10
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE14); // 14
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE15); // 15
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE3);  // 3
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE2);  // 2
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE1);  // 1
-    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);  // 0
-    
-    exint_default_para_init(&exint_init_struct);
-    
-    exint_init_struct.line_enable = TRUE;
-    exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
-    exint_init_struct.line_select = EXINT_LINE_0 | EXINT_LINE_1 | EXINT_LINE_2 |
-                                    EXINT_LINE_3 | EXINT_LINE_10 | 
-                                    EXINT_LINE_11| EXINT_LINE_14 | EXINT_LINE_15; 
-    
-    exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
-    exint_init(&exint_init_struct);
-    
-    exint_flag_clear(EXINT_LINE_0);
-    exint_flag_clear(EXINT_LINE_1);
-    exint_flag_clear(EXINT_LINE_2);
-    exint_flag_clear(EXINT_LINE_3);
-    exint_flag_clear(EXINT_LINE_10);
-    exint_flag_clear(EXINT_LINE_11);
-    exint_flag_clear(EXINT_LINE_14);
-    exint_flag_clear(EXINT_LINE_15);
-    
-    nvic_irq_enable(EXINT0_IRQn, 5, 0);
-    nvic_irq_enable(EXINT1_IRQn, 5, 0);
-    nvic_irq_enable(EXINT2_IRQn, 5, 0);
-    nvic_irq_enable(EXINT3_IRQn, 5, 0);
-    nvic_irq_enable(EXINT15_10_IRQn, 5, 0);
-}
-
-
-// Настройка датчиков обрыва нагрузки (GPIO).
-void di_load_sens_init(simple_gpio_t *sens)
-{
-    gpio_init_type gpio_init_struct;
-    
-    gpio_default_para_init(&gpio_init_struct);
-        
-    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
-    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
-    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-    gpio_init_struct.gpio_pins           = sens->pin;
-    gpio_init(sens->port, &gpio_init_struct); 
-}
-
-
-// Таймер антидребезга для дискретных входов
-void di_tim_init(void)
-{
-    crm_clocks_freq_type crm_clocks_freq_struct = {0};
-    
-    crm_clocks_freq_get(&crm_clocks_freq_struct);
-    
-    nvic_irq_disable(TMR8_BRK_TMR12_IRQn);
-    
-    crm_periph_clock_enable(CRM_TMR12_PERIPH_CLOCK, TRUE);
-
-    // 1 Hz
-    tmr_base_init(TMR12, 9, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
-    tmr_cnt_dir_set(TMR12, TMR_COUNT_UP);
-    
-    NVIC_ClearPendingIRQ(TMR8_BRK_TMR12_IRQn);
-    nvic_irq_enable(TMR8_BRK_TMR12_IRQn, 5, 0);
-    
-    tmr_flag_clear(TMR12, TMR_OVF_FLAG);
-    tmr_interrupt_enable(TMR12, TMR_OVF_INT, TRUE);
-    tmr_counter_value_set(TMR12, 0);
-    tmr_counter_enable(TMR12, TRUE);  
-}
-
-
-// IRQ таймера антидребезга дискретных входов
-void TMR8_BRK_TMR12_IRQHandler(void)
-{
-    if(tmr_flag_get(TMR12, TMR_OVF_FLAG) != RESET)
-    {
-        tmr_flag_clear(TMR12, TMR_OVF_FLAG);
-
-        debounce();
-    }
-}
-
-
-// Установка состояний дискретных входов (вкл./выкл.)
-void di_set_state(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        settings.di[i].state = (uint8_t)((settings.di_state_bits >> i) & 1);
-    }
-}
-
-
-// Пробегает по всему массиву структур цифровых входов.
-// Если режим входа изменился 
-void di_set(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        if (((settings.di_mode_bits >> i) & 1) != d_inputs[i].mode) 
-        {
-            d_inputs[i].mode = ((settings.di_mode_bits >> i) & 1);
-            if (d_inputs[i].mode == 0) 
-            {
-                d_inputs[i].cnt = 0;
-                d_inputs[i].p_flag = false;
-                di_cnt[i] = 0;
-            }
-            else
-            {
-                di_state_bit &= ~(1 << i);
-            }
-        }
-    }
-}
-
-//
-uint8_t di_get(uint8_t channel)
-{
-    uint8_t ret = 0;
-    
-    ret = (uint8_t)(di_state_bit >> channel & 1);
-    
-    return  ret;
-}
-
-
-// Функция антидребезка. Вызывается в прерывании таймера.
-void debounce(void)
-{
-    for (int i = 0; i < DI_NUMBER; i++)
-    {
-        if ((d_inputs[i].p_flag) && (d_inputs[i].mode == 0)){
-            if (++d_inputs[i].cnt == settings.di_debounce[i]) {
-                d_inputs[i].cnt = 0;
-                d_inputs[i].p_flag = false;
-                
-                di_state[i] = (uint16_t)gpio_input_data_bit_read(d_inputs[i].port, d_inputs[i].pin);
-                
-                if (!di_state[i]) {
-                    di_state_bit &= ~(1 << i); // снять бит
-                    leds[i].state = LED_OFF;
-                }
-                else {
-                    di_state_bit |= di_state[i] << i;
-                    leds[i].state = LED_ON;
-                }
-            }
-        }
-    }
-}
-
-
-// Периодический опрос дискретнрых входов и датчиков обрыва нагрузки
-void di_task(void *params)
-{
-    for (;;)
-    {
-        // Дискретные входы
-        for (int i = 0; i < DI_NUMBER; i++)
-        {
-            // Режим обычного входа
-            if (d_inputs[i].mode == 0)
-            {
-                di_state[i] = (uint16_t)gpio_input_data_bit_read(d_inputs[i].port, d_inputs[i].pin);
-                
-                if (!di_state[i]) {
-                    di_state_bit &= ~(1 << i); // снять бит
-                    leds[i].state = LED_OFF;
-                }
-                else {
-                    di_state_bit |= di_state[i] << i;
-                    leds[i].state = LED_ON;
-                }
-            }
-        }
-        
-       
-        // Датчики обрыва нагрузки
-        for (int i = 0; i < DI_NUMBER; i++)
-        {                           
-            di_load_state[i] = (uint16_t)gpio_input_data_bit_read(di_load[i].port, di_load[i].pin);
-            
-            // Текущее состояние датчиков нагрузки.
-            if (!di_load_state[i]) {
-                di_load_state_bit &= ~(1 << i);  // снять бит
-            }
-            else {
-                di_load_state_bit |= 1 << i;
-            }
-            
-            // Установка битов достоверности
-            // Если 0 (выход разомкнут), то состояние достоверно и нужно 
-            // выставить соответствующий бит
-            if (!(output_state_bit & (1 << i))) {
-                di_credibility_state_bit |= 1 << i;
-            }
-            else { 
-                di_credibility_state_bit &= ~(1 << i);
-            }  
-        }
-            
-        vTaskDelay(100);
-    }
-}
-
-// -------------------------------------------------------------------------- // 
-//        Обработчики прерываний EXTI для режима счетных входов
-
-// IN_8 GPIOA_0
-void EXINT0_IRQHandler(void)
-{
-    if (exint_flag_get(EXINT_LINE_0) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_0);
-        if (d_inputs[7].mode == 0)
-            d_inputs[7].p_flag = true;
-        else { 
-            if (d_inputs[7].cnt_flag) {
-                di_cnt[7]++;
-                d_inputs[7].cnt_flag = false;
-            }
-            else
-                d_inputs[7].cnt_flag = true;
-        }
-    }
-}
-
-// IN_7 GPIOA_1
-void EXINT1_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_1) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_1);
-        if (d_inputs[6].mode == 0)
-            d_inputs[6].p_flag = true;
-        else { 
-            if (d_inputs[6].cnt_flag) {
-                di_cnt[6]++;
-                d_inputs[6].cnt_flag = false;
-            }
-            else
-                d_inputs[6].cnt_flag = true;
-        }
-    }
-}
-
-// IN_6 GPIOA_2
-void EXINT2_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_2) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_2);
-        if (d_inputs[5].mode == 0)
-            d_inputs[5].p_flag = true;
-        else { 
-            if (d_inputs[5].cnt_flag) {
-                di_cnt[5]++;
-                d_inputs[5].cnt_flag = false;
-            }
-            else
-                d_inputs[5].cnt_flag = true;
-        }
-    }
-}
-
-// IN_5 GPIOA_3
-void EXINT3_IRQHandler(void)
-{
-    if(exint_flag_get(EXINT_LINE_3) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_3);
-        if (d_inputs[4].mode == 0)
-            d_inputs[4].p_flag = true;
-        else { 
-            if (d_inputs[4].cnt_flag) {
-                di_cnt[4]++;
-                d_inputs[4].cnt_flag = false;
-            }
-            else
-                d_inputs[4].cnt_flag = true;
-        }
-    }
-}
-
-// IN_1, IN_2, IN_3, IN_4
-void EXINT15_10_IRQHandler(void)
-{
-    // IN_2 GPIOB_10
-    if (exint_flag_get(EXINT_LINE_10) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_10);
-        if (d_inputs[1].mode == 0)
-            d_inputs[1].p_flag = true;
-        else { 
-            if (d_inputs[1].cnt_flag) {
-                di_cnt[1]++;
-                d_inputs[1].cnt_flag = false;
-            }
-            else
-                d_inputs[1].cnt_flag = true;
-        }
-    }
-    // IN_1 GPIOB_11
-    else if (exint_flag_get(EXINT_LINE_11) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_11);
-        if (d_inputs[0].mode == 0)
-            d_inputs[0].p_flag = true;
-        else { 
-            if (d_inputs[0].cnt_flag) {
-                di_cnt[0]++;
-                d_inputs[0].cnt_flag = false;
-            }
-            else
-                d_inputs[0].cnt_flag = true;
-        }
-    }
-    // IN_3 GPIOE_14
-    else if (exint_flag_get(EXINT_LINE_14) != RESET)  
-    {
-        exint_flag_clear(EXINT_LINE_14);
-        if (d_inputs[2].mode == 0)
-            d_inputs[2].p_flag = true;
-        else { 
-            if (d_inputs[2].cnt_flag) {
-                di_cnt[2]++;
-                d_inputs[2].cnt_flag = false;
-            }
-            else
-                d_inputs[2].cnt_flag = true;
-        }
-    }
-    // IN_4 GPIOE_15
-    else if (exint_flag_get(EXINT_LINE_15) != RESET) 
-    {
-        exint_flag_clear(EXINT_LINE_15);
-        if (d_inputs[3].mode == 0)
-            d_inputs[3].p_flag = true;
-        else { 
-            if (d_inputs[3].cnt_flag) {
-                di_cnt[3]++;
-                d_inputs[3].cnt_flag = false;
-            }
-            else
-                d_inputs[3].cnt_flag = true;
-        }
-    }    
-}
-
-#endif
+#include "at32f403a_407.h"
+#include "digital_input.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "settings_api.h"
+#include "io_utils.h"
+#include "mux.h"
+#include <stdio.h>
+
+#if defined (MDIO_88)
+
+// Цифровые входы
+// *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
+din_t d_inputs[DI_NUMBER] = {
+    {GPIOB, GPIO_PINS_11, 0, 0, 0, false, false}, // 1   
+    {GPIOB, GPIO_PINS_10, 0, 0, 0, false, false}, // 2
+    {GPIOE, GPIO_PINS_14, 0, 0, 0, false, false}, // 3 перенесли {GPIOB, GPIO_PINS_1,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE1,  0},
+    {GPIOE, GPIO_PINS_15, 0, 0, 0, false, false}, // 4 перенесли {GPIOB, GPIO_PINS_0,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE0,  0},
+    {GPIOA, GPIO_PINS_3,  0, 0, 0, false, false}, // 5
+    {GPIOA, GPIO_PINS_2,  0, 0, 0, false, false}, // 6
+    {GPIOA, GPIO_PINS_1,  0, 0, 0, false, false}, // 7
+    {GPIOA, GPIO_PINS_0,  0, 0, 0, false, false}  // 8
+};
+
+// Датчики обрыва нагрузки
+simple_gpio_t di_load[DI_NUMBER] = {
+    {GPIOD, GPIO_PINS_0},
+    {GPIOD, GPIO_PINS_1},
+    {GPIOC, GPIO_PINS_13},
+    {GPIOC, GPIO_PINS_0},
+    {GPIOC, GPIO_PINS_10},
+    {GPIOD, GPIO_PINS_4},
+    {GPIOE, GPIO_PINS_4},
+    {GPIOC, GPIO_PINS_3}
+};
+
+// -------------------------------------------------------------------------- //
+// Текущие параметры
+
+uint32_t di_cnt[DI_NUMBER];             // счетчики входов
+
+uint16_t di_state[DI_NUMBER];           // состояние входов
+uint16_t di_state_bit;
+
+uint16_t di_load_state[DO_NUMBER];      // состояние датчиков обрыва нагрузки
+uint16_t di_load_state_bit;             // состояние датчиков обрыва нагрузки (битовое поле)
+
+uint16_t di_output_state[DO_NUMBER];    // состояние датчиков неисправности выходов
+uint16_t di_output_state_bit;           // состояние датчиков неисправности выходов (битовое поле)
+
+uint16_t di_credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
+uint16_t di_credibility_state_bit;         // достоверность состояния датчиков нагрузки
+
+
+// Настройка периферии дискретных входов (GPIO, EXTI, TIM).
+// Настройка датчиков обрыва нагрузки (GPIO).
+// Вызывается единственный раз при старте контроллера.
+// Периферия настраивается однозначно и только один раз.
+void di_init(void)
+{
+    // Входы
+    for (int i = 0; i < DI_NUMBER; i++) {
+        di_base_init(&d_inputs[i]);
+        di_load_sens_init(&di_load[i]);
+    }
+    
+    // EXTI
+    di_exti_init();
+    
+    // Таймер для антидребезга
+    di_tim_init();
+}
+
+
+// Настройка GPIO дискретных входов
+void di_base_init(din_t *input)
+{
+    gpio_init_type gpio_init_struct;
+
+    gpio_default_para_init(&gpio_init_struct);
+        
+    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_init_struct.gpio_pins           = input->pin;
+    gpio_init(input->port, &gpio_init_struct);
+}
+
+
+// Настройка EXTI дискретных входов
+void di_exti_init(void)
+{
+    exint_init_type exint_init_struct;
+    
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE11); // 11
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE10); // 10
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE14); // 14
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOE, GPIO_PINS_SOURCE15); // 15
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE3);  // 3
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE2);  // 2
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE1);  // 1
+    gpio_exint_line_config(GPIO_PORT_SOURCE_GPIOA, GPIO_PINS_SOURCE0);  // 0
+    
+    exint_default_para_init(&exint_init_struct);
+    
+    exint_init_struct.line_enable = TRUE;
+    exint_init_struct.line_mode = EXINT_LINE_INTERRUPUT;
+    exint_init_struct.line_select = EXINT_LINE_0 | EXINT_LINE_1 | EXINT_LINE_2 |
+                                    EXINT_LINE_3 | EXINT_LINE_10 | 
+                                    EXINT_LINE_11| EXINT_LINE_14 | EXINT_LINE_15; 
+    
+    exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
+    exint_init(&exint_init_struct);
+    
+    exint_flag_clear(EXINT_LINE_0);
+    exint_flag_clear(EXINT_LINE_1);
+    exint_flag_clear(EXINT_LINE_2);
+    exint_flag_clear(EXINT_LINE_3);
+    exint_flag_clear(EXINT_LINE_10);
+    exint_flag_clear(EXINT_LINE_11);
+    exint_flag_clear(EXINT_LINE_14);
+    exint_flag_clear(EXINT_LINE_15);
+    
+    nvic_irq_enable(EXINT0_IRQn, 5, 0);
+    nvic_irq_enable(EXINT1_IRQn, 5, 0);
+    nvic_irq_enable(EXINT2_IRQn, 5, 0);
+    nvic_irq_enable(EXINT3_IRQn, 5, 0);
+    nvic_irq_enable(EXINT15_10_IRQn, 5, 0);
+}
+
+
+// Настройка датчиков обрыва нагрузки (GPIO).
+void di_load_sens_init(simple_gpio_t *sens)
+{
+    gpio_init_type gpio_init_struct;
+    
+    gpio_default_para_init(&gpio_init_struct);
+        
+    gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_init_struct.gpio_mode           = GPIO_MODE_INPUT;  
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_init_struct.gpio_pins           = sens->pin;
+    gpio_init(sens->port, &gpio_init_struct); 
+}
+
+
+// Таймер антидребезга для дискретных входов
+void di_tim_init(void)
+{
+    crm_clocks_freq_type crm_clocks_freq_struct = {0};
+    
+    crm_clocks_freq_get(&crm_clocks_freq_struct);
+    
+    nvic_irq_disable(TMR8_BRK_TMR12_IRQn);
+    
+    crm_periph_clock_enable(CRM_TMR12_PERIPH_CLOCK, TRUE);
+
+    // 1 Hz
+    tmr_base_init(TMR12, 9, (crm_clocks_freq_struct.ahb_freq / 10000) - 1);
+    tmr_cnt_dir_set(TMR12, TMR_COUNT_UP);
+    
+    NVIC_ClearPendingIRQ(TMR8_BRK_TMR12_IRQn);
+    nvic_irq_enable(TMR8_BRK_TMR12_IRQn, 5, 0);
+    
+    tmr_flag_clear(TMR12, TMR_OVF_FLAG);
+    tmr_interrupt_enable(TMR12, TMR_OVF_INT, TRUE);
+    tmr_counter_value_set(TMR12, 0);
+    tmr_counter_enable(TMR12, TRUE);  
+}
+
+
+// IRQ таймера антидребезга дискретных входов
+void TMR8_BRK_TMR12_IRQHandler(void)
+{
+    if(tmr_flag_get(TMR12, TMR_OVF_FLAG) != RESET)
+    {
+        tmr_flag_clear(TMR12, TMR_OVF_FLAG);
+
+        debounce();
+    }
+}
+
+
+// Установка состояний дискретных входов (вкл./выкл.)
+void di_set_state(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        settings.di[i].state = (uint8_t)((settings.di_state_bits >> i) & 1);
+    }
+}
+
+
+// Пробегает по всему массиву структур цифровых входов.
+// Если режим входа изменился 
+void di_set(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if (((settings.di_mode_bits >> i) & 1) != d_inputs[i].mode) 
+        {
+            d_inputs[i].mode = ((settings.di_mode_bits >> i) & 1);
+            if (d_inputs[i].mode == 0) 
+            {
+                d_inputs[i].cnt = 0;
+                d_inputs[i].p_flag = false;
+                di_cnt[i] = 0;
+            }
+            else
+            {
+                di_state_bit &= ~(1 << i);
+            }
+        }
+    }
+}
+
+//
+uint8_t di_get(uint8_t channel)
+{
+    uint8_t ret = 0;
+    
+    ret = (uint8_t)(di_state_bit >> channel & 1);
+    
+    return  ret;
+}
+
+
+// Функция антидребезка. Вызывается в прерывании таймера.
+void debounce(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if ((d_inputs[i].p_flag) && (d_inputs[i].mode == 0)){
+            if (++d_inputs[i].cnt == settings.di_debounce[i]) {
+                d_inputs[i].cnt = 0;
+                d_inputs[i].p_flag = false;
+                
+                di_state[i] = (uint16_t)gpio_input_data_bit_read(d_inputs[i].port, d_inputs[i].pin);
+                
+                if (!di_state[i]) {
+                    di_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    di_state_bit |= di_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+    }
+}
+
+
+// Периодический опрос дискретнрых входов и датчиков обрыва нагрузки
+void di_task(void *params)
+{
+    for (;;)
+    {
+        // Дискретные входы
+        for (int i = 0; i < DI_NUMBER; i++)
+        {
+            // Режим обычного входа
+            if (d_inputs[i].mode == 0)
+            {
+                di_state[i] = (uint16_t)gpio_input_data_bit_read(d_inputs[i].port, d_inputs[i].pin);
+                
+                if (!di_state[i]) {
+                    di_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    di_state_bit |= di_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+        
+       
+        // Датчики обрыва нагрузки
+        for (int i = 0; i < DI_NUMBER; i++)
+        {                           
+            di_load_state[i] = (uint16_t)gpio_input_data_bit_read(di_load[i].port, di_load[i].pin);
+            
+            // Текущее состояние датчиков нагрузки.
+            if (!di_load_state[i]) {
+                di_load_state_bit &= ~(1 << i);  // снять бит
+            }
+            else {
+                di_load_state_bit |= 1 << i;
+            }
+            
+            // Установка битов достоверности
+            // Если 0 (выход разомкнут), то состояние достоверно и нужно 
+            // выставить соответствующий бит
+            if (!(output_state_bit & (1 << i))) {
+                di_credibility_state_bit |= 1 << i;
+            }
+            else { 
+                di_credibility_state_bit &= ~(1 << i);
+            }  
+        }
+            
+        vTaskDelay(100);
+    }
+}
+
+// -------------------------------------------------------------------------- // 
+//        Обработчики прерываний EXTI для режима счетных входов
+
+// IN_8 GPIOA_0
+void EXINT0_IRQHandler(void)
+{
+    if (exint_flag_get(EXINT_LINE_0) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_0);
+        if (d_inputs[7].mode == 0)
+            d_inputs[7].p_flag = true;
+        else { 
+            if (d_inputs[7].cnt_flag) {
+                di_cnt[7]++;
+                d_inputs[7].cnt_flag = false;
+            }
+            else
+                d_inputs[7].cnt_flag = true;
+        }
+    }
+}
+
+// IN_7 GPIOA_1
+void EXINT1_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_1) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_1);
+        if (d_inputs[6].mode == 0)
+            d_inputs[6].p_flag = true;
+        else { 
+            if (d_inputs[6].cnt_flag) {
+                di_cnt[6]++;
+                d_inputs[6].cnt_flag = false;
+            }
+            else
+                d_inputs[6].cnt_flag = true;
+        }
+    }
+}
+
+// IN_6 GPIOA_2
+void EXINT2_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_2) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_2);
+        if (d_inputs[5].mode == 0)
+            d_inputs[5].p_flag = true;
+        else { 
+            if (d_inputs[5].cnt_flag) {
+                di_cnt[5]++;
+                d_inputs[5].cnt_flag = false;
+            }
+            else
+                d_inputs[5].cnt_flag = true;
+        }
+    }
+}
+
+// IN_5 GPIOA_3
+void EXINT3_IRQHandler(void)
+{
+    if(exint_flag_get(EXINT_LINE_3) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_3);
+        if (d_inputs[4].mode == 0)
+            d_inputs[4].p_flag = true;
+        else { 
+            if (d_inputs[4].cnt_flag) {
+                di_cnt[4]++;
+                d_inputs[4].cnt_flag = false;
+            }
+            else
+                d_inputs[4].cnt_flag = true;
+        }
+    }
+}
+
+// IN_1, IN_2, IN_3, IN_4
+void EXINT15_10_IRQHandler(void)
+{
+    // IN_2 GPIOB_10
+    if (exint_flag_get(EXINT_LINE_10) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_10);
+        if (d_inputs[1].mode == 0)
+            d_inputs[1].p_flag = true;
+        else { 
+            if (d_inputs[1].cnt_flag) {
+                di_cnt[1]++;
+                d_inputs[1].cnt_flag = false;
+            }
+            else
+                d_inputs[1].cnt_flag = true;
+        }
+    }
+    // IN_1 GPIOB_11
+    else if (exint_flag_get(EXINT_LINE_11) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_11);
+        if (d_inputs[0].mode == 0)
+            d_inputs[0].p_flag = true;
+        else { 
+            if (d_inputs[0].cnt_flag) {
+                di_cnt[0]++;
+                d_inputs[0].cnt_flag = false;
+            }
+            else
+                d_inputs[0].cnt_flag = true;
+        }
+    }
+    // IN_3 GPIOE_14
+    else if (exint_flag_get(EXINT_LINE_14) != RESET)  
+    {
+        exint_flag_clear(EXINT_LINE_14);
+        if (d_inputs[2].mode == 0)
+            d_inputs[2].p_flag = true;
+        else { 
+            if (d_inputs[2].cnt_flag) {
+                di_cnt[2]++;
+                d_inputs[2].cnt_flag = false;
+            }
+            else
+                d_inputs[2].cnt_flag = true;
+        }
+    }
+    // IN_4 GPIOE_15
+    else if (exint_flag_get(EXINT_LINE_15) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_15);
+        if (d_inputs[3].mode == 0)
+            d_inputs[3].p_flag = true;
+        else { 
+            if (d_inputs[3].cnt_flag) {
+                di_cnt[3]++;
+                d_inputs[3].cnt_flag = false;
+            }
+            else
+                d_inputs[3].cnt_flag = true;
+        }
+    }    
+}
+
+#endif

+ 57 - 54
fw/modules/io/digital_input.h

@@ -1,54 +1,57 @@
-#ifndef __DIGITAL_INPUT_H
-#define __DIGITAL_INPUT_H
-
-#include <stdbool.h>
-#include "io.h"
-
-
-
-//
-void di_init(void);
-
-//
-void di_base_init(din_t *input);
-
-//
-void di_exti_init(void);
-
-// 
-void di_tim_init(void);
-
-//
-void di_load_sens_init(simple_gpio_t *sens);
-
-//
-void di_set_state(void);
-
-//
-void di_set(void);
-
-//
-uint8_t di_get(uint8_t channel);
-
-//
-void debounce(void);
-
-// Периодический опрос входов и датчиков обрыва нагрузки
-void di_task(void *params);
-
-
-
-extern uint32_t di_cnt[DI_NUMBER];   // счетчики входов
-
-extern uint16_t di_state[DI_NUMBER]; // состояние входа
-extern uint16_t di_state_bit;        // битовое поле
-
-extern uint16_t di_load_state[DO_NUMBER];  // состояние датчиков нагрузки
-extern uint16_t di_load_state_bit;
-
-extern uint16_t di_credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
-extern uint16_t di_credibility_state_bit;  // достоверность состояния датчиков нагрузки
-
-
-#endif  // __DIGITAL_INPUT_H
-
+#ifndef __DIGITAL_INPUT_H
+#define __DIGITAL_INPUT_H
+
+#include <stdbool.h>
+#include "io.h"
+
+
+
+//
+void di_init(void);
+
+//
+void di_base_init(din_t *input);
+
+//
+void di_exti_init(void);
+
+// 
+void di_tim_init(void);
+
+//
+void di_load_sens_init(simple_gpio_t *sens);
+
+//
+void di_set_state(void);
+
+//
+void di_set(void);
+
+//
+uint8_t di_get(uint8_t channel);
+
+//
+void debounce(void);
+
+// Периодический опрос входов и датчиков обрыва нагрузки
+void di_task(void *params);
+
+
+
+extern uint32_t di_cnt[];
+
+extern uint16_t di_state[];
+extern uint16_t di_state_bit; 
+
+extern uint16_t di_load_state[];  
+extern uint16_t di_load_state_bit;
+
+extern uint16_t di_output_state[];    
+extern uint16_t di_output_state_bit;  
+
+extern uint16_t di_credibility_state[];
+extern uint16_t di_credibility_state_bit;
+
+
+#endif  // __DIGITAL_INPUT_H
+

+ 9 - 0
fw/modules/io/digital_output.c

@@ -81,6 +81,15 @@ void di_gpio_init(out_t *out, uint8_t index)
     do_update(out, index) ;
 }
 
+// Установка состояний дискретных выходов (вкл./выкл.)
+void do_set_state(void)
+{
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        settings.dout[i].state = (uint8_t)((settings.do_state_bits >> i) & 1);
+    }
+}
+
 //
 void do_set_common(void)
 {

+ 3 - 0
fw/modules/io/digital_output.h

@@ -11,6 +11,9 @@ void do_init(void);
 //
 void di_gpio_init(out_t *out, uint8_t index);
 
+//
+void do_set_state(void);
+
 //
 void do_set_common(void);
 

+ 129 - 121
fw/modules/io/io.h

@@ -1,121 +1,129 @@
-#ifndef __IO_H
-#define __IO_H
-
-#include <stdbool.h>
-
-
-// -------------------------------------------------------------------------- //
-// Дискретые входы
-
-#define DI_NUMBER           8   // Количество входов
-
-#define DI_MODE_IN          0   // Режим обычного входа
-
-#define DI_MODE_CNT         1   // Режим счетного входа
-
-
-// -------------------------------------------------------------------------- //
-// Дискретные выходы
-
-#define DO_NUMBER           8   // Количество выходов
-
-#define DEBOUNCE_CNT        50
-
-// -------------------------------------------------------------------------- //
-// Аналоговые входы. 
-
-#define AI_ALL_NUMBER       16  // Общее количество
-
-#define AI_COMMON_NUMBER    12  // Основные 12
-
-#define AI_ADD_NUMBER       4   // Дополнительные 4 входа
-
-// -------------------------------------------------------------------------- //
-// Аналоговые выходы. 
-
-#define AO_NUMBER           4   // Количество выходов
-
-// -------------------------------------------------------------------------- //
-
-//
-void io_port_enable(void);
-
-
-// -------------------------------------------------------------------------- //
-
-typedef struct
-{
-    gpio_type *port;
-    uint16_t pin;
-    
-} simple_gpio_t;
-
-
-typedef struct
-{
-    uint8_t state;          // 0 - выкл, 1 - вкл
-    
-} di_t;
-
-
-typedef struct 
-{
-    gpio_type *port;
-    uint16_t pin;
-    uint16_t mode;  // 0 - обычный вход, 1 - счетный вход
-    uint32_t deb_counter;
-    uint32_t cnt;
-    bool p_flag;
-    bool cnt_flag;
-    
-} din_t;
-
-
-typedef struct
-{
-    gpio_type *port;
-    uint16_t pin;
-    uint16_t mode;  // 0 - обычный выход, 1 - режим ШИМ
-    uint16_t pwm_period_cnt;
-    uint16_t pwm_duty_cnt;
-    uint16_t pwm_flag;
-    uint16_t pwm_period;
-    uint16_t pwm_duty;
-    
-} out_t;
-
-
-extern uint16_t output_state_bit;
-extern uint16_t output_mode_bit;
-extern uint16_t output_pwm[];
-extern uint16_t output_pwm_save[];
-extern uint16_t output_pwm_period[];
-extern uint16_t output_pwm_period_save[];
-
-
-//
-// контроль состояний - обрыв, КЗ, норма
-typedef struct
-{
-    uint16_t state;         // состояние выхода
-    uint16_t pwm;           // 
-    uint16_t mode;          // режим работы, 0 - выход, 1 - PWM
-    uint16_t smode_state;   // значение в безопасном режиме,
-                            // 0 - разомкнут, 1 - замкнут
-    uint16_t smode_pwm;     // значение PWM в безопасном режиме (%)
-    uint16_t normal_state;  // нормальное состояние выхода
-                            // 0 - разомкнут, 1 - замкнут
-} output_t;
-
-
-typedef struct
-{
-    uint16_t smode;         // безопасный режим 0 - включен, 1 - выключен
-    uint16_t com_timeout;   // время ожидания запроса от мастера
-} system_t;
-
-
-
-
-#endif  // __IO_H
-
+#ifndef __IO_H
+#define __IO_H
+
+#include <stdbool.h>
+
+
+// -------------------------------------------------------------------------- //
+// Дискретые входы
+
+#define DI_NUMBER           8   // Количество входов
+
+#define DI_MODE_IN          0   // Режим обычного входа
+
+#define DI_MODE_CNT         1   // Режим счетного входа
+
+
+// -------------------------------------------------------------------------- //
+// Дискретные выходы
+
+#define DO_NUMBER           8   // Количество выходов
+
+#define DEBOUNCE_CNT        50
+
+// -------------------------------------------------------------------------- //
+// Аналоговые входы. 
+
+#define AI_ALL_NUMBER       16  // Общее количество
+
+#define AI_COMMON_NUMBER    12  // Основные 12
+
+#define AI_ADD_NUMBER       4   // Дополнительные 4 входа
+
+// -------------------------------------------------------------------------- //
+// Аналоговые выходы. 
+
+#define AO_NUMBER           4   // Количество выходов
+
+// -------------------------------------------------------------------------- //
+
+//
+void io_port_enable(void);
+
+
+// -------------------------------------------------------------------------- //
+
+typedef struct
+{
+    gpio_type *port;
+    uint16_t pin;
+    
+} simple_gpio_t;
+
+//
+typedef struct
+{
+    uint8_t state;          // 0 - выкл, 1 - вкл
+    
+} di_t;
+
+//
+typedef struct
+{
+    uint8_t state;          // 0 - выкл, 1 - вкл
+    
+} do_t;
+
+
+
+typedef struct 
+{
+    gpio_type *port;
+    uint16_t pin;
+    uint16_t mode;  // 0 - обычный вход, 1 - счетный вход
+    uint32_t deb_counter;
+    uint32_t cnt;
+    bool p_flag;
+    bool cnt_flag;
+    
+} din_t;
+
+
+typedef struct
+{
+    gpio_type *port;
+    uint16_t pin;
+    uint16_t mode;  // 0 - обычный выход, 1 - режим ШИМ
+    uint16_t pwm_period_cnt;
+    uint16_t pwm_duty_cnt;
+    uint16_t pwm_flag;
+    uint16_t pwm_period;
+    uint16_t pwm_duty;
+    
+} out_t;
+
+
+extern uint16_t output_state_bit;
+extern uint16_t output_mode_bit;
+extern uint16_t output_pwm[];
+extern uint16_t output_pwm_save[];
+extern uint16_t output_pwm_period[];
+extern uint16_t output_pwm_period_save[];
+
+
+//
+// контроль состояний - обрыв, КЗ, норма
+typedef struct
+{
+    uint16_t state;         // состояние выхода
+    uint16_t pwm;           // 
+    uint16_t mode;          // режим работы, 0 - выход, 1 - PWM
+    uint16_t smode_state;   // значение в безопасном режиме,
+                            // 0 - разомкнут, 1 - замкнут
+    uint16_t smode_pwm;     // значение PWM в безопасном режиме (%)
+    uint16_t normal_state;  // нормальное состояние выхода
+                            // 0 - разомкнут, 1 - замкнут
+} output_t;
+
+
+typedef struct
+{
+    uint16_t smode;         // безопасный режим 0 - включен, 1 - выключен
+    uint16_t com_timeout;   // время ожидания запроса от мастера
+} system_t;
+
+
+
+
+#endif  // __IO_H
+

+ 271 - 237
fw/modules/modbus/modbus_dio_params.c

@@ -1,237 +1,271 @@
-#include "at32f403a_407.h"
-#include "modbus_dio_params.h"
-#include "modbus_params.h"
-#include "digital_input.h"
-#include "digital_output.h"
-#include "settings_api.h"
-
-extern mb_param_t mb_param[];
-
-#if defined (MDIO_88)
-
-
-//
-uint16_t mb_init_dio_params(uint16_t i)
-{
-    uint16_t index = i;
-    uint16_t addr = 0;  
-  
-    // Статус дискретных входов (вкл./выкл.)
-    mb_param[index].reg = 0x0100;
-	mb_param[index].size = 1;
-	mb_param[index].param = (uint8_t*)&settings.di_state_bits;  
-	mb_param[index].set = mb_set_di_state;
-    mb_param[index].get = NULL;
-    mb_param[index].check_handler = mb_check_dummy;
-    
-    index++;
-  
-    // Текущее состояние входов
-    mb_param[index].reg = 0x0101;
-	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++;
-    }
-    
-    return index;
-}
-
-
-
-// -------------------------------------------------------------------------- //
-//                          Установка параметров
-// -------------------------------------------------------------------------- //
-
-//
-mb_delay_action_t mb_set_di_state(void)
-{
-    di_set_state();
-    return MB_SAVE_SETTINGS;
-}
-
-//
-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;
-}
-
-#endif
-
+#include "at32f403a_407.h"
+#include "modbus_dio_params.h"
+#include "modbus_params.h"
+#include "digital_input.h"
+#include "digital_output.h"
+#include "settings_api.h"
+
+extern mb_param_t mb_param[];
+
+#if defined (MDIO_88)
+
+
+//
+uint16_t mb_init_dio_params(uint16_t i)
+{
+    uint16_t index = i;
+    uint16_t addr = 0;  
+  
+    // Статус дискретных входов (вкл./выкл.)
+    mb_param[index].reg = 0x0100;
+	mb_param[index].size = 1;
+	mb_param[index].param = (uint8_t*)&settings.di_state_bits;  
+	mb_param[index].set = mb_set_di_state;
+    mb_param[index].get = NULL;
+    mb_param[index].check_handler = mb_check_dummy;
+    
+    index++;
+  
+    // Текущее состояние входов
+    mb_param[index].reg = 0x0101;
+	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++;
+    
+    // Текущее датчиков неисправности выходов
+    mb_param[index].reg = 0x0131;
+	mb_param[index].size = 1;
+	mb_param[index].param = (uint8_t*)&di_output_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*)&settings.do_state_bits;  
+	mb_param[index].set = mb_set_do_state;
+    mb_param[index].get = NULL;
+    mb_param[index].check_handler = mb_check_dummy;
+    
+    index++;
+    
+    // Текущее состояние выходов
+    mb_param[index].reg = 0x0201;
+	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++;
+    }
+    
+    return index;
+}
+
+
+
+// -------------------------------------------------------------------------- //
+//                          Установка параметров
+// -------------------------------------------------------------------------- //
+
+//
+mb_delay_action_t mb_set_di_state(void)
+{
+    di_set_state();
+    return MB_SAVE_SETTINGS;
+}
+
+//
+mb_delay_action_t mb_set_din_mode(void)
+{
+    di_set();
+    return MB_NO_ACTION;
+}
+
+
+// -------------------------------------------------------------------------
+// Параметры дискретных выходов
+
+//
+mb_delay_action_t mb_set_do_state(void)
+{
+    do_set_state();
+    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;
+}
+
+#endif
+

+ 42 - 39
fw/modules/modbus/modbus_dio_params.h

@@ -1,40 +1,43 @@
-#ifndef __MODBUS_DIO_PARAMS_H
-#define __MODBUS_DIO_PARAMS_H
-
-#include "mb.h"
-#include "mbport.h"
-#include "modbus.h"
-#include <stdbool.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-  
-//
-uint16_t mb_init_dio_params(uint16_t i);
-  
-// -------------------------------------------------------------------------- //
-//                          Установка параметров
-// -------------------------------------------------------------------------- //
-
-//
-mb_delay_action_t mb_set_di_state(void);
-
-//
-mb_delay_action_t mb_set_din_mode(void);
-
-//
-mb_delay_action_t mb_set_do(void);
-
-//
-mb_delay_action_t mb_set_do_mode(void);
-
-
-
-#ifdef __cplusplus
-}
-#endif
-
+#ifndef __MODBUS_DIO_PARAMS_H
+#define __MODBUS_DIO_PARAMS_H
+
+#include "mb.h"
+#include "mbport.h"
+#include "modbus.h"
+#include <stdbool.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+  
+//
+uint16_t mb_init_dio_params(uint16_t i);
+  
+// -------------------------------------------------------------------------- //
+//                          Установка параметров
+// -------------------------------------------------------------------------- //
+
+//
+mb_delay_action_t mb_set_di_state(void);
+
+//
+mb_delay_action_t mb_set_din_mode(void);
+
+//
+mb_delay_action_t mb_set_do_state(void);
+
+//
+mb_delay_action_t mb_set_do(void);
+
+//
+mb_delay_action_t mb_set_do_mode(void);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
 #endif // __MODBUS_DIO_PARAMS_H

+ 1 - 1
fw/modules/modbus/modbus_params.h

@@ -12,7 +12,7 @@ extern "C" {
 #endif
 
 #if defined (MDIO_88)  
-#define MB_PARAM_MAX			90
+#define  MB_PARAM_MAX			92
 #endif
 
 #if defined (MAI_12)  

+ 245 - 244
fw/modules/settings/settings_api.h

@@ -1,244 +1,245 @@
-#ifndef SETTINGS_API_H
-#define SETTINGS_API_H
-
-#include "at32f403a_407.h"
-#include "model_cfg.h"
-#include "usart.h"
-#include "sys_api.h"
-#include "io.h"
-#include "mb.h"
-#include "mbport.h"
-#include "log.h"
-#include "analog_input.h"
-#include "analog_output.h"
-#include <stdbool.h>
-
-
-// Изменить версию если поменялась структура настроек
-#define SETTINGS_VERSION    0x01
-
-
-// ------------------------------------------------------------------- //
-//					 	Граничные значения
-// ------------------------------------------------------------------- //
-
-#define MAX_ARCHIVE_PERIOD  43200
-
-// ------------------------------------------------------------------- //
-//					 	Настройки лога и архива
-// ------------------------------------------------------------------- //
-
-#define ARCH_DIO_CH_NUMBER              8
-
-#define ARCH_AI_CH_NUMBER               12 //12  
-
-
-// ------------------------------------------------------------------- //
-//					 		Draft
-// ------------------------------------------------------------------- //
-
-/*
-1. Uptime (uint32_t)                    // +
-2. Realtime (unix timestamp, uint32_t)  // +
-3. Версия прошивки                      // +
-4. Модель (char 16 байт)                // +
-
-*/
-
-
-
-// ------------------------------------------------------------------- //
-//					 		Modbus
-// ------------------------------------------------------------------- //
-
-#define MB_STOP_BIT_MASK    0x03
-#define MB_STOP_BIT_1       0x00
-#define MB_STOP_BIT_2       0x02
-
-#define MB_PARITY_MASK      (0x03 << 3)
-#define MB_NO_PAR           (0x00 << 3)
-#define MB_EVEN_PAR         (0x02 << 3)
-#define MB_ODD_PAR          (0x03 << 3)
-
-#define MB_BRD_MASK         (0x07 << 5)
-#define MB_BRD_2400         (0x00 << 5)
-#define MB_BRD_4800         (0x01 << 5)
-#define MB_BRD_9600         (0x02 << 5)
-#define MB_BRD_19200        (0x03 << 5)
-#define MB_BRD_38400        (0x04 << 5)
-#define MB_BRD_57600        (0x05 << 5)
-#define MB_BRD_115200       (0x06 << 5)
-
-
-
-// Modbus 
-typedef struct
-{
-	rate_t     baud;		// Скорость порта 
-	parity_t   parity;		// Четность 
-	databits_t databits;	// Число бит данных
-	stopbits_t stopbits;	// Число стоп-бит  
-    
-} modbus_t;
-
-
-// Общая структура настроек для IAP и FW
-typedef struct
-{
-    uint16_t    mb_port;    // Настройки порта для modbus
-    //char model[MODEL_LEN];  // Модель
-} com_settings_t;
-
-
-#if 0
-// Дискретные входы
-typedef struct
-{
-    uint16_t debounce_time; // период антидребезга в мс (0 - 10 сек)
-} dinput_t;
-#endif
-
-
-// Полная структура настроек
-typedef struct
-{
-    com_settings_t  com_settings;
-    uint32_t    critical_section_crc;
-/* WARNING! До поля CritSecCRC включительно структура настроек должна быть
-* идентичной между бутлоадером и основным ПО и не должна изменяться при обновлении ПО.
-* Контроль целостности настроек внутри IAP выполняется только для критической секции,
-* т.к. контроль целостности всей структуры не имеет смысла
-* (структура настроек всегда будет отличаться внутри основного ПО).
-* В случае повреждения критического сектора, загружаются параметры по умолчанию. */    
-    
-    uint16_t    settings_version;   // Версия структуры настроек 
-    uint32_t    control_word;       // Слово для контроля целостности структуры настроек
-    
-#if defined (MDIO_88)          
-    
-    di_t        di[DI_NUMBER];      //
-    uint16_t    di_state_bits;      //
-    
-    
-    
-    uint16_t    di_mode_bits;          // режим работы, 0 - вход, 1 - счетчик импульсов
-    uint16_t    di_norm_state_bits;    // нормальное состояние (0 - разомкнут, 1 - замкнут)        
-    uint16_t    di_debounce[DI_NUMBER]; // Дискретные входы
-    
-    uint16_t    do_mode_bits;       // режим работы выхода 0 - выход, 1 - ШИМ
-    uint16_t    do_bits;            // последнее сохраненное значение на выходах
-    uint16_t    do_save_bits;       // значение на выходах в бесопасном режиме работы
-    uint16_t    do_pwm[DO_NUMBER];  // значение заполнения ШИМ
-    uint16_t    do_pwm_save[DO_NUMBER]; // значение заполнения ШИМ в безопасном режиме
-    uint16_t    do_pwm_period[DO_NUMBER];  // период ШИМ в [0.1с (10..1000)]
-    uint16_t    do_pwm_period_save[DO_NUMBER]; // период ШИМ в безопасном режиме [0.1с (10..1000)]
-    
-    uint16_t    period_archive[ARCH_DIO_CH_NUMBER]; // период архивирования
-#endif
-
-#if defined (MAI_12)
-    ai_t        ai[AI_COMMON_NUMBER];   // 
-    ai_t        ai_add[AI_ADD_NUMBER];  //
-     
-    uint16_t    ai_state_bits;      // статус входа (для 12 основных), 0 - выкл, 1 - вкл
-    uint16_t    ai_mode_bits;       // режим работы входов (для 12 основных), 0 - измерение напряжения, 1 - тока
-    uint16_t    ext_sens_power;     // питание внешних датчиков, 0 - выкл, 1 - вкл
-    
-    uint16_t    period_archive[ARCH_AI_CH_NUMBER]; // период архивирования
-#endif    
-
-#if defined (MAO_4)    
-    
-    ao_t        ao[AO_NUMBER];      // параметры выходов 
-    ao_t        ao_save[AO_NUMBER]; // параметры выходов в безопасном режиме
-    
-    uint16_t    ao_state_bits;      // статус выхода, 0 - выкл, 1 - вкл
-    uint16_t    ao_state_save_bits; // статус выхода в безопасном режиме, 0 - выкл, 1 - вкл
-    uint16_t    ao_mode_bits;       // режим работы выходов, 0 - напряжения, 1 - ток
-    uint16_t    ao_mode_save_bits;  // режим работы выходов в безопасном режиме, 0 - напряжения, 1 - ток
-    
-#endif    
-    
-    bool        save_mode;          // безопасный режим, 0 - выкл, 1 - вкл
-    uint16_t    save_delay;         // время ожидания опроса (сек.)
-      
-    uint8_t     info[32];           // Пользовательская информация. Текстовая строка.
-    
-    
-} settings_t;
-
-
-
-// Загрузка структуры настроек из flesh
-void settings_load(settings_t *settings);
-
-//
-void init_settings(void);
-
-//
-void settings_read_from_flash(uint8_t *data, uint32_t size);
-
-//
-uint32_t settings_get_crc(settings_t *settings);
-
-//
-uint32_t settings_get_crit_sec_crc(settings_t *settings);
-
-// Сброс всех настроек в значения по умолчанию
-void settings_set_all_default(void);
-
-
-// -------------------------------------------------------------------------- //
-// Настройки по умолчанию
-
-//
-void settings_set_modbus_def(uint16_t *mb_port);
-
-//
-void settings_conv_modbus_def(modbus_t *mb_settings, uint16_t *mb_port);
-
-// Установка параметров Modbus
-void settings_set_modbus_params(uint16_t mb_port);
-
-//
-uint32_t settings_get_mb_baud(modbus_t *mb_settings);
-
-//
-eMBParity settings_get_mb_par(modbus_t *mb_settings);
-
-//
-void settings_init_mb_port(uint8_t mb_addr);
-
-// -------------------------------------------------------------------------- //
-
-// Запись структуры настроек во flash
-bool settings_save(settings_t *settings);
-
-//
-bool settings_save_with_log(void);
-
-//
-bool settings_write_to_flash(uint8_t *data, uint32_t size);
-
-// Очистка сектора настроек
-void settings_erase_flash_sector(void);
-
-//
-bool settings_is_changed(settings_t *new_settings);
-
-//
-void settings_print(void);
-
-
-// Системные настройки
-extern sys_settings_t sys_settings;
-
-// Копия системных настроек
-extern sys_settings_t temp_sys_settings;
-
-// Общая структура настроек
-extern settings_t settings;
-
-
-#endif /* #ifndef SETTINGS_API_H */
-
+#ifndef SETTINGS_API_H
+#define SETTINGS_API_H
+
+#include "at32f403a_407.h"
+#include "model_cfg.h"
+#include "usart.h"
+#include "sys_api.h"
+#include "io.h"
+#include "mb.h"
+#include "mbport.h"
+#include "log.h"
+#include "analog_input.h"
+#include "analog_output.h"
+#include <stdbool.h>
+
+
+// Изменить версию если поменялась структура настроек
+#define SETTINGS_VERSION    0x01
+
+
+// ------------------------------------------------------------------- //
+//					 	Граничные значения
+// ------------------------------------------------------------------- //
+
+#define MAX_ARCHIVE_PERIOD  43200
+
+// ------------------------------------------------------------------- //
+//					 	Настройки лога и архива
+// ------------------------------------------------------------------- //
+
+#define ARCH_DIO_CH_NUMBER              8
+
+#define ARCH_AI_CH_NUMBER               12 //12  
+
+
+// ------------------------------------------------------------------- //
+//					 		Draft
+// ------------------------------------------------------------------- //
+
+/*
+1. Uptime (uint32_t)                    // +
+2. Realtime (unix timestamp, uint32_t)  // +
+3. Версия прошивки                      // +
+4. Модель (char 16 байт)                // +
+
+*/
+
+
+
+// ------------------------------------------------------------------- //
+//					 		Modbus
+// ------------------------------------------------------------------- //
+
+#define MB_STOP_BIT_MASK    0x03
+#define MB_STOP_BIT_1       0x00
+#define MB_STOP_BIT_2       0x02
+
+#define MB_PARITY_MASK      (0x03 << 3)
+#define MB_NO_PAR           (0x00 << 3)
+#define MB_EVEN_PAR         (0x02 << 3)
+#define MB_ODD_PAR          (0x03 << 3)
+
+#define MB_BRD_MASK         (0x07 << 5)
+#define MB_BRD_2400         (0x00 << 5)
+#define MB_BRD_4800         (0x01 << 5)
+#define MB_BRD_9600         (0x02 << 5)
+#define MB_BRD_19200        (0x03 << 5)
+#define MB_BRD_38400        (0x04 << 5)
+#define MB_BRD_57600        (0x05 << 5)
+#define MB_BRD_115200       (0x06 << 5)
+
+
+
+// Modbus 
+typedef struct
+{
+	rate_t     baud;		// Скорость порта 
+	parity_t   parity;		// Четность 
+	databits_t databits;	// Число бит данных
+	stopbits_t stopbits;	// Число стоп-бит  
+    
+} modbus_t;
+
+
+// Общая структура настроек для IAP и FW
+typedef struct
+{
+    uint16_t    mb_port;    // Настройки порта для modbus
+    //char model[MODEL_LEN];  // Модель
+} com_settings_t;
+
+
+#if 0
+// Дискретные входы
+typedef struct
+{
+    uint16_t debounce_time; // период антидребезга в мс (0 - 10 сек)
+} dinput_t;
+#endif
+
+
+// Полная структура настроек
+typedef struct
+{
+    com_settings_t  com_settings;
+    uint32_t    critical_section_crc;
+/* WARNING! До поля CritSecCRC включительно структура настроек должна быть
+* идентичной между бутлоадером и основным ПО и не должна изменяться при обновлении ПО.
+* Контроль целостности настроек внутри IAP выполняется только для критической секции,
+* т.к. контроль целостности всей структуры не имеет смысла
+* (структура настроек всегда будет отличаться внутри основного ПО).
+* В случае повреждения критического сектора, загружаются параметры по умолчанию. */    
+    
+    uint16_t    settings_version;   // Версия структуры настроек 
+    uint32_t    control_word;       // Слово для контроля целостности структуры настроек
+    
+#if defined (MDIO_88)          
+    
+    di_t        di[DI_NUMBER];      //
+    uint16_t    di_state_bits;      //
+    
+    do_t        dout[DO_NUMBER];    // 
+    uint16_t    do_state_bits;      //    
+    
+    uint16_t    di_mode_bits;          // режим работы, 0 - вход, 1 - счетчик импульсов
+    uint16_t    di_norm_state_bits;    // нормальное состояние (0 - разомкнут, 1 - замкнут)        
+    uint16_t    di_debounce[DI_NUMBER]; // Дискретные входы
+    
+    uint16_t    do_mode_bits;       // режим работы выхода 0 - выход, 1 - ШИМ
+    uint16_t    do_bits;            // последнее сохраненное значение на выходах
+    uint16_t    do_save_bits;       // значение на выходах в бесопасном режиме работы
+    uint16_t    do_pwm[DO_NUMBER];  // значение заполнения ШИМ
+    uint16_t    do_pwm_save[DO_NUMBER]; // значение заполнения ШИМ в безопасном режиме
+    uint16_t    do_pwm_period[DO_NUMBER];  // период ШИМ в [0.1с (10..1000)]
+    uint16_t    do_pwm_period_save[DO_NUMBER]; // период ШИМ в безопасном режиме [0.1с (10..1000)]
+    
+    uint16_t    period_archive[ARCH_DIO_CH_NUMBER]; // период архивирования
+#endif
+
+#if defined (MAI_12)
+    ai_t        ai[AI_COMMON_NUMBER];   // 
+    ai_t        ai_add[AI_ADD_NUMBER];  //
+     
+    uint16_t    ai_state_bits;      // статус входа (для 12 основных), 0 - выкл, 1 - вкл
+    uint16_t    ai_mode_bits;       // режим работы входов (для 12 основных), 0 - измерение напряжения, 1 - тока
+    uint16_t    ext_sens_power;     // питание внешних датчиков, 0 - выкл, 1 - вкл
+    
+    uint16_t    period_archive[ARCH_AI_CH_NUMBER]; // период архивирования
+#endif    
+
+#if defined (MAO_4)    
+    
+    ao_t        ao[AO_NUMBER];      // параметры выходов 
+    ao_t        ao_save[AO_NUMBER]; // параметры выходов в безопасном режиме
+    
+    uint16_t    ao_state_bits;      // статус выхода, 0 - выкл, 1 - вкл
+    uint16_t    ao_state_save_bits; // статус выхода в безопасном режиме, 0 - выкл, 1 - вкл
+    uint16_t    ao_mode_bits;       // режим работы выходов, 0 - напряжения, 1 - ток
+    uint16_t    ao_mode_save_bits;  // режим работы выходов в безопасном режиме, 0 - напряжения, 1 - ток
+    
+#endif    
+    
+    bool        save_mode;          // безопасный режим, 0 - выкл, 1 - вкл
+    uint16_t    save_delay;         // время ожидания опроса (сек.)
+      
+    uint8_t     info[32];           // Пользовательская информация. Текстовая строка.
+    
+    
+} settings_t;
+
+
+
+// Загрузка структуры настроек из flesh
+void settings_load(settings_t *settings);
+
+//
+void init_settings(void);
+
+//
+void settings_read_from_flash(uint8_t *data, uint32_t size);
+
+//
+uint32_t settings_get_crc(settings_t *settings);
+
+//
+uint32_t settings_get_crit_sec_crc(settings_t *settings);
+
+// Сброс всех настроек в значения по умолчанию
+void settings_set_all_default(void);
+
+
+// -------------------------------------------------------------------------- //
+// Настройки по умолчанию
+
+//
+void settings_set_modbus_def(uint16_t *mb_port);
+
+//
+void settings_conv_modbus_def(modbus_t *mb_settings, uint16_t *mb_port);
+
+// Установка параметров Modbus
+void settings_set_modbus_params(uint16_t mb_port);
+
+//
+uint32_t settings_get_mb_baud(modbus_t *mb_settings);
+
+//
+eMBParity settings_get_mb_par(modbus_t *mb_settings);
+
+//
+void settings_init_mb_port(uint8_t mb_addr);
+
+// -------------------------------------------------------------------------- //
+
+// Запись структуры настроек во flash
+bool settings_save(settings_t *settings);
+
+//
+bool settings_save_with_log(void);
+
+//
+bool settings_write_to_flash(uint8_t *data, uint32_t size);
+
+// Очистка сектора настроек
+void settings_erase_flash_sector(void);
+
+//
+bool settings_is_changed(settings_t *new_settings);
+
+//
+void settings_print(void);
+
+
+// Системные настройки
+extern sys_settings_t sys_settings;
+
+// Копия системных настроек
+extern sys_settings_t temp_sys_settings;
+
+// Общая структура настроек
+extern settings_t settings;
+
+
+#endif /* #ifndef SETTINGS_API_H */
+

+ 63 - 58
fw/modules/settings/settings_dio.c

@@ -1,58 +1,63 @@
-#include "at32f403a_407.h" 
-#include "settings_api.h"
-#include "settings_dio.h"
-
-#if defined (MDIO_88)
-
-//
-void settings_dio_set_all_default(void)
-{
-    // Дискретные/счетные входы
-    settings_din_def(&settings);
-    
-    // Выходы
-    settings_do_def(&settings);
-    
-    // Время ведения архива по каждому каналу (сек.)
-    for (uint8_t i = 0; i < ARCH_DIO_CH_NUMBER; i++) {
-        settings.period_archive[i] = 3600;
-    }
-}
-
-// Установить параметры дискретных входов по умолчанию
-void settings_din_def(settings_t *settings)
-{
-    // Все входы выключены
-    settings->di_state_bits = 0;
-    
-    // Параметры входов в обычном режиме
-    for (int i = 0; i < DI_NUMBER; i++) {
-        settings->di[i].state = 0;
-    }
-  
-  
-    settings->di_mode_bits = 0;
-    settings->di_norm_state_bits = 0;
-    
-    for (int i = 0; i < DI_NUMBER; i++) {
-        settings->di_debounce[i] = 50;
-    }
-}
-
-// Выходы
-void settings_do_def(settings_t *settings)
-{
-    settings->do_mode_bits = 0; // режим работы выхода (обычный выход)
-    settings->do_bits = 0;      // последнее сохраненное значение 
-    settings->do_save_bits = 0;
-    
-    for (uint8_t i = 0; i < DO_NUMBER; i++)
-    {
-        settings->do_pwm[i] = 30;
-        settings->do_pwm_save[i] = 30; // значение на выходах в бесопасном режиме работы
-        settings->do_pwm_period[i] = 50;
-        settings->do_pwm_period_save[i] = 50;
-    }
-}
-
-#endif
+#include "at32f403a_407.h" 
+#include "settings_api.h"
+#include "settings_dio.h"
+
+#if defined (MDIO_88)
+
+//
+void settings_dio_set_all_default(void)
+{
+    // Дискретные/счетные входы
+    settings_din_def(&settings);
+    
+    // Выходы
+    settings_do_def(&settings);
+    
+    // Время ведения архива по каждому каналу (сек.)
+    for (uint8_t i = 0; i < ARCH_DIO_CH_NUMBER; i++) {
+        settings.period_archive[i] = 3600;
+    }
+}
+
+// Установить параметры дискретных входов по умолчанию
+void settings_din_def(settings_t *settings)
+{
+    // Все входы выключены
+    settings->di_state_bits = 0;
+    
+    // Параметры входов в обычном режиме
+    for (int i = 0; i < DI_NUMBER; i++) {
+        settings->di[i].state = 0;
+    }
+    
+    settings->di_mode_bits = 0;
+    settings->di_norm_state_bits = 0;
+    
+    for (int i = 0; i < DI_NUMBER; i++) {
+        settings->di_debounce[i] = 50;
+    }
+}
+
+// Выходы
+void settings_do_def(settings_t *settings)
+{
+    settings->do_state_bits = 0;
+  
+    for (uint8_t i = 0; i < DO_NUMBER; i++) {
+        settings->dout[i].state = 0;
+    }
+  
+    settings->do_mode_bits = 0; // режим работы выхода (обычный выход)
+    settings->do_bits = 0;      // последнее сохраненное значение 
+    settings->do_save_bits = 0;
+    
+    for (uint8_t i = 0; i < DO_NUMBER; i++)
+    {
+        settings->do_pwm[i] = 30;
+        settings->do_pwm_save[i] = 30; // значение на выходах в бесопасном режиме работы
+        settings->do_pwm_period[i] = 50;
+        settings->do_pwm_period_save[i] = 50;
+    }
+}
+
+#endif

二進制
output/fw.bin


File diff suppressed because it is too large
+ 418 - 423
project/ewarm/iap/iap.dep


File diff suppressed because it is too large
+ 553 - 554
project/ewarm/module_universal_io.dep


+ 37 - 25
tools/digital_io.py

@@ -17,7 +17,7 @@ class IO_Digital(IO_Module):
         super().__init__(self.modbus)
         self.log = DigitalLogReader(self.modbus)
   
-    '''Запрос параметров'''
+    '''Запрос параметров дискретных входов'''
 
     # 0x0100 - Состояние входов (вкл./выкл.)
     def get_inputs_state(self) -> str:
@@ -32,32 +32,32 @@ class IO_Digital(IO_Module):
     # 0x0101 - 0x0110 Счетчики импульсов
     def get_inputs_counters(self):
         data = []
-        for i in range(DIO_REGS['in_cnt'], DIO_REGS['in_cnt'] + 16, 2):
+        first_reg = DioReg.IN_CNT.value
+        for i in range(first_reg, first_reg + 16, 2):
             data.append(self.modbus.read_uint32_holding(i))
         return data
 
-    # 0x0101 - 0x0110 Счетчики импульсов
-    def get_inputs_counters(self):
-        data = []
-        for i in range(DIO_REGS['in_cnt'], DIO_REGS['in_cnt'] + 16, 2):
-            data.append(self.modbus.read_uint32_holding(i))
-        return data                              
-
     # 0x0120 - режим работы входов
     def get_inputs_mode(self):
-        data = self.modbus.read_holding_registers(DIO_REGS['in_mode'], 1)
+        data = self.modbus.read_holding_registers(DioReg.IN_MODE.value, 1)
         return format(data[0], '08b')
 
     # 0x0122 - нормальное состояние входов
     def get_inputs_norm_state(self):
-        data = self.modbus.read_holding_registers(DIO_REGS['in_norm'], 1)
+        data = self.modbus.read_holding_registers(DioReg.IN_NORM.value, 1)
         return format(data[0], '08b')
 
-    # 0x0124 - время антидребезга (ms)
+    # 0x0124 - время антидребезга отдельного входа (ms)
     def get_debounce_channel(self, input):
-        data = self.modbus.read_holding_registers(DIO_REGS['in_deb_start'] + input - 1, 1)
+        data = self.modbus.read_holding_registers(DioReg.IN_DEBOUNCE.value + input - 1, 1)
         return data[0]
 
+    # 0x0124 - время антидребезга всех входов (ms)
+    def get_debounce_channels(self):
+        return self.modbus.read_holding_registers(DioReg.IN_DEBOUNCE.value, 8)
+
+    '''Запрос датчиков обрыва нагрузки'''
+
     # 0x0130
     def get_loads_bit(self):
         data = self.modbus.read_holding_registers(DIO_REGS['load_bits'], 1)
@@ -67,36 +67,48 @@ class IO_Digital(IO_Module):
     def get_cred_bit(self):
         data = self.modbus.read_holding_registers(DIO_REGS['cred_bits'], 1)
         return format(data[0], '08b')
+    
 
-    def get_debounce_channels(self):
-        return self.modbus.read_holding_registers(DIO_REGS['in_deb_start'], 8)
-
-    '''Установка параметров'''
+    '''Установка параметров дискретных входов'''
 
     # 0x0100 - Состояние входов (вкл./выкл.)
     def set_inputs_state(self, val):
         self.modbus.write_holding_register(DioReg.IN_STATE.value, val)
 
-    #
+    # 0x0120 - Режим работы всех входов
     def set_inputs_mode(self, val):
-        self.modbus.write_holding_register(DIO_REGS['in_mode'], val)
+        self.modbus.write_holding_register(DioReg.IN_MODE.value, val)
 
-    #        
+    # 0x0120 - Режим работы отдельного входа
     def set_input_mode(self, input, val):
-        ret = self.modbus.read_holding_registers(DIO_REGS['in_mode'], 1)
+        ret = self.modbus.read_holding_registers(DioReg.IN_MODE.value, 1)
         if val == 1:
             data = ret[0] | (0b1 << (input - 1))
         else:
             data = ret[0] & ~(0b1 << (input - 1))
         self.set_inputs_mode(data)
 
-    # 0x0200 - текущее состояние выходов в обычно режиме
+
+    '''Запрос параметров дискретных входов'''
+
+    # 0x0200 - Состояние выходов (вкл./выкл.)
+    def get_outputs_state(self):
+        data = self.modbus.read_holding_registers(DioReg.OUT_STATE.value , 1)
+        return format(data[0], '08b')
+
+    '''Установка параметров дискретных выходов'''
+
+    # 0x0200 - Состояние выходов (вкл./выкл.)
+    def set_outputs_state(self, val):
+        self.modbus.write_holding_register(DioReg.OUT_STATE.value, val)
+
+    # 0x0201 - текущее состояние выходов в обычном режиме
     def set_outputs(self, val):
-        self.modbus.write_holding_register(DIO_REGS['out_cur'], val)
+        self.modbus.write_holding_register(DioReg.OUT_BITS.value, val)
 
-    # Установить значение на конкретном выходе [1..8]
+    # 0x0201 - Установить значение на конкретном выходе [1..8]
     def set_output(self, output, val):
-        ret = self.modbus.read_holding_registers(DIO_REGS['out_cur'], 1)
+        ret = self.modbus.read_holding_registers(DioReg.OUT_BITS.value, 1)
         if val == 1:
             data = ret[0] | (0b1 << (output - 1))
         else:

+ 8 - 2
tools/mb_registers.py

@@ -5,8 +5,7 @@ reg_table = {'out_cur': 0x0200, 'out_mode': 0x0202, 'out_mode_save': 0x0203, 'pw
              'rtc_sinhro': 0x0804, 'log_info': 0x0900, 'log_ent': 0x0901, 
              'arch_cap': 0x0902, 'arch_ent': 0x0903, 'archive_per': 0x0904}
 
-DIO_REGS = {'in_bits': 0x0100, 'in_cnt': 0x0102,'in_mode': 0x0120, 'in_norm': 0x0122,
-            'in_deb_start': 0x124, 'load_bits': 0x0130, 'cred_bits': 0x0131, 'out_cur': 0x0200}
+DIO_REGS = {'load_bits': 0x0130, 'cred_bits': 0x0131, 'out_cur': 0x0200}
 
 AI_REGS = {'ain_state': 0x0300, 'ain_mode': 0x0301, 'ain_alarm': 0x0302, 'esens_pow': 0x0303, 
            'ain_gain': 0x0310, 'ain_raw': 0x0320, 'ain_fil': 0x0330}
@@ -18,6 +17,13 @@ class DioReg(Enum):
 
     IN_STATE        = 0x0100 # Состояние входов (вкл./выкл.)
     IN_BITS         = 0x0101 # Текущее состояние входов
+    IN_CNT          = 0x0102 # Счетчики импульсов
+    IN_MODE         = 0x0120 # Режим работы входов (битовое поле)
+    IN_NORM         = 0x0122 # Нормальное состояние входов
+    IN_DEBOUNCE     = 0x0124 # Время антидребезга (ms)
+
+    OUT_STATE       = 0x0200 # Состояние выходов (вкл./выкл.)
+    OUT_BITS        = 0x0201 # Текущее состояние выходов    
 
 
 class AoReg(Enum):

Some files were not shown because too many files changed in this diff