Ver Fonte

Тесты датчиков нагрузки.

TelenkovDmitry há 8 meses atrás
pai
commit
e823b9c9bc

+ 34 - 1
fw/modules/io/input.c

@@ -4,6 +4,7 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "mux.h"
+#include "output.h"
 #include <stdio.h>
 
 
@@ -146,7 +147,7 @@ void io_test(void)
     
 }
 
-//
+// Периодический опрос входов
 void input_task(void *params)
 {
     for (;;)
@@ -169,6 +170,38 @@ void input_task(void *params)
                 }
             }
         }
+        
+        
+#if 0        
+        uint16_t load_state[DO_NUMBER];     // состояние датчиков нагрузки
+       //uint16_t load_state_bit;
+
+        uint16_t credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
+        uint16_t credibility_state_bit;         // достоверность состояния датчиков нагрузки
+#endif
+        
+        for (int i = 0; i < DO_NUMBER; i++)
+        {                           
+            load_state[i] = (uint16_t)gpio_input_data_bit_read(load_sens[i].port, load_sens[i].pin);
+            
+            // Текущее состояние датчиков нагрузки.
+            if (!load_state[i]) {
+                load_state_bit &= ~(1 << i);  // снять бит
+            }
+            else {
+                load_state_bit |= 1 << i;
+            }
+            
+            // Установка битов достоверности
+            // Если 0 (выход разомкнут), то состояние достоверно и нужно 
+            // выставить соответствующий бит
+            if (!(output_state_bit & (1 << i))) {
+                credibility_state_bit |= 1 << i;
+            }
+            else { 
+                credibility_state_bit &= ~(1 << i);
+            }  
+        }
             
         vTaskDelay(100);
     }

+ 7 - 2
fw/modules/io/io.c

@@ -9,11 +9,16 @@
 #include <stdio.h>
 
 
-uint16_t input_state[DI_NUMBER];     // состояние входа
+uint16_t input_state[DI_NUMBER];    // состояние входов
 uint16_t input_state_bit;
 
+uint16_t load_state[DO_NUMBER];     // состояние датчиков нагрузки
+uint16_t load_state_bit;
+
+uint16_t credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
+uint16_t credibility_state_bit;         // достоверность состояния датчиков нагрузки
+
 
-//uint16_t output_state[DO_NUMBER];     // состояние входа
 uint16_t output_state_bit;
 uint16_t output_mode_bit;
 uint16_t output_pwm[DO_NUMBER];

+ 146 - 140
fw/modules/io/io.h

@@ -1,140 +1,146 @@
-#ifndef __IO_H
-#define __IO_H
-
-#include <stdbool.h>
-
-// Период опроса входов 100 мс
-
-// -------------------------------------------------------------------------- //
-// Дискретые входы
-
-#define DI_NUMBER       8   // Количество входов
-
-#define DI_MODE_IN      0   // Режим обычного входа
-
-#define DI_MODE_CNT     1   // Режим счетного входа
-
-
-// -------------------------------------------------------------------------- //
-// Выходы
-#define DO_NUMBER       8    // Количество выходов
-
-#define DEBOUNCE_CNT    50
-
-// Прочие параметры из других модулей для передачи по modbus
-
-//uint32_t uptime;
-
-
-// -------------------------------------------------------------------------- //
-
-//
-void io_port_init(void);
-
-//
-void io_init(void);
-
-//
-void io_tim_init(void);
-
-// -------------------------------------------------------------------------- //
-
-typedef struct
-{
-    gpio_type *port;
-    uint16_t pin;
-    
-} simple_gpio_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 input_state[DI_NUMBER];      // состояние входа
-extern uint16_t input_state_bit;             // битовое поле
-
-extern uint32_t input_cnt[DI_NUMBER];       // счетчики входов
-
-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[];
-
-//uint16_t output_state[DI_NUMBER];    // состояние выхода, 0 - норма, 1 - обрыв, 2 - КЗ
-
-
-// -------------------------------------------------------------------------- //
-// Структуры настроек. Хранятся во внутренней памяти контроллера.
-
-
-//
-// контроль состояний - обрыв, КЗ, норма
-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;
-
-
-// Структура системных настроек
-/*
-typedef struct 
-{
-	uint16_t        model;			// Модель
-	uint32_t        proddate;		// Дата производства
-	uint32_t        serial;			// Серийный номер
-	uint8_t         fw_version[8];	// Версия ПО
-	uint8_t         test_state;		// Статус тестирования
-	
-} sys_settings_t;
-
-*/
-
-
-
-#endif  // __IO_H
-
+#ifndef __IO_H
+#define __IO_H
+
+#include <stdbool.h>
+
+// Период опроса входов 100 мс
+
+// -------------------------------------------------------------------------- //
+// Дискретые входы
+
+#define DI_NUMBER       8   // Количество входов
+
+#define DI_MODE_IN      0   // Режим обычного входа
+
+#define DI_MODE_CNT     1   // Режим счетного входа
+
+
+// -------------------------------------------------------------------------- //
+// Выходы
+#define DO_NUMBER       8    // Количество выходов
+
+#define DEBOUNCE_CNT    50
+
+// Прочие параметры из других модулей для передачи по modbus
+
+//uint32_t uptime;
+
+
+// -------------------------------------------------------------------------- //
+
+//
+void io_port_init(void);
+
+//
+void io_init(void);
+
+//
+void io_tim_init(void);
+
+// -------------------------------------------------------------------------- //
+
+typedef struct
+{
+    gpio_type *port;
+    uint16_t pin;
+    
+} simple_gpio_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 input_state[DI_NUMBER]; // состояние входа
+extern uint16_t input_state_bit;        // битовое поле
+
+extern uint16_t load_state[DO_NUMBER];  // состояние датчиков нагрузки
+extern uint16_t load_state_bit;
+
+extern uint16_t credibility_state[DO_NUMBER];  // достоверность состояния датчиков нагрузки
+extern uint16_t credibility_state_bit;  // достоверность состояния датчиков нагрузки
+
+extern uint32_t input_cnt[DI_NUMBER];   // счетчики входов
+
+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[];
+
+//uint16_t output_state[DI_NUMBER];    // состояние выхода, 0 - норма, 1 - обрыв, 2 - КЗ
+
+
+// -------------------------------------------------------------------------- //
+// Структуры настроек. Хранятся во внутренней памяти контроллера.
+
+
+//
+// контроль состояний - обрыв, КЗ, норма
+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;
+
+
+// Структура системных настроек
+/*
+typedef struct 
+{
+	uint16_t        model;			// Модель
+	uint32_t        proddate;		// Дата производства
+	uint32_t        serial;			// Серийный номер
+	uint8_t         fw_version[8];	// Версия ПО
+	uint8_t         test_state;		// Статус тестирования
+	
+} sys_settings_t;
+
+*/
+
+
+
+#endif  // __IO_H
+

+ 368 - 369
fw/modules/io/output.c

@@ -1,369 +1,368 @@
-#include "at32f403a_407.h"
-#include "output.h"
-#include "FreeRTOS.h"
-#include "task.h"
-#include "settings_api.h"
-#include "io_utils.h"
-#include <stdio.h>
-
-
-out_t outputs[DO_NUMBER] = {
-    {GPIOC, GPIO_PINS_12, 0, 0, 0, false, 0, 0},   // -
-    {GPIOD, GPIO_PINS_2,  0, 0, 0, false, 0, 0},   // -
-    {GPIOE, GPIO_PINS_6,  0, 0, 0, false, 0, 0},   // TMR9_CH2 (remap)
-    {GPIOC, GPIO_PINS_1,  0, 0, 0, false, 0, 0},   // -
-    {GPIOC, GPIO_PINS_11, 0, 0, 0, false, 0, 0},   // -
-    {GPIOD, GPIO_PINS_3,  0, 0, 0, false, 0, 0},   // -
-    {GPIOE, GPIO_PINS_5,  0, 0, 0, false, 0, 0},   // TMR9_CH1 (remap)
-    {GPIOC, GPIO_PINS_2,  0, 0, 0, false, 0, 0}    // -
-};
-
-
-simple_gpio_t load_sens[DO_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}
-};
-
-
-
-//
-void out_gpio_init(out_t *out, uint8_t index)
-{
-    gpio_init_type gpio_init_struct;
-
-    
-    // Выход
-    if (out->mode == 0)
-    {
-        gpio_default_para_init(&gpio_init_struct);
-        
-        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
-        gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
-        gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;  
-        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-        gpio_init_struct.gpio_pins           = out->pin;
-        gpio_init(out->port, &gpio_init_struct); 
-    }
-    
-    do_update(out, index) ;
-}
-
-//
-void do_set_common(void)
-{
-    bool flag = false;
-    
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        // 
-        if ((settings.do_bits & (1 << i)) != (output_state_bit & (1 << i))) {
-            settings.do_bits = output_state_bit;
-            flag = true;
-        } 
-        else if ((settings.do_mode_bits & (1 << i)) != (output_mode_bit & (1 << i))) {
-            settings.do_mode_bits ^= (1 << i);
-            settings.do_mode_bits = output_mode_bit;
-            flag = true;
-        }  
-        else if (settings.do_pwm[i] != output_pwm[i]) {
-            settings.do_pwm[i] = output_pwm[i];
-            flag = true;
-        }
-        else if (settings.do_pwm_save[i] != output_pwm_save[i]) {
-            settings.do_pwm_save[i] = output_pwm_save[i];
-            flag = true;
-        }
-        else if (settings.do_pwm_period [i] != output_pwm_period[i]) {
-            settings.do_pwm_period[i] = output_pwm_period[i];
-            flag = true;
-        }
-        else if (settings.do_pwm_period_save[i] != output_pwm_period_save[i]) {
-            settings.do_pwm_period_save[i] = output_pwm_period_save[i];
-            flag = true;
-        }
- 
-        if (flag)
-            do_update(&outputs[i], i);
-    }
-}
-
-//
-void do_set(void)
-{
-    if (output_state_bit == settings.do_bits) 
-        return;
-    
-    // Состояние выхода/выходов изменилось
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        if ((settings.do_bits & (1 << i)) != (output_state_bit & (1 << i))) 
-        {
-            do_update(&outputs[i], i);
-        }
-    }
-    
-    // Сохраним новое значение выходов в настройках
-    settings.do_bits = output_state_bit;
-}
-
-// Установка значения на выходе 
-void do_update(out_t *out, uint8_t i)
-{
-    // Режим ШИМ
-    if (settings.do_mode_bits & (1 << i)) {
-        // Безопасный режим включен
-        if (save_mode_get())
-            do_set_pwm(settings.do_pwm_period_save[i], settings.do_pwm_save[i], i);
-        else
-            do_set_pwm(settings.do_pwm_period[i], settings.do_pwm[i], i);
-    }
-    // Режим обычного выхода
-    else {
-        out->mode = 0;
-        // Безопасный режим включен
-        if (save_mode_get())
-            do_set_out(out, settings.do_save_bits & (1 << i));
-        else
-            do_set_out(out, settings.do_bits & (1 << i));
-    }
-}
-
-//
-void do_set_mode(void)
-{
-    if (output_mode_bit == settings.do_mode_bits)
-        return;
-  
-    // Состояние выхода/выходов изменилось
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        if ((settings.do_mode_bits & (1 << i)) != (output_mode_bit & (1 << i)))
-        {
-            settings.do_mode_bits ^= (1 << i);
-            do_update(&outputs[i], i);
-        }
-    }
-  
-    settings.do_mode_bits = output_mode_bit;
-}
-
-//#define PWM_PERIOD_TEST     20
-//#define PWM_DUTY_TEST       10
-void do_set_pwm(uint16_t period, uint16_t duty, uint8_t index)
-{
-    uint16_t duty_calc;
-  
-    if (duty == 0)
-        duty_calc = 0;
-    else
-        duty_calc = (duty*period/100 < 1) ? 1 : duty*period/100;
-    
-    outputs[index].pwm_flag = false;
-    outputs[index].pwm_period_cnt = 0;
-    outputs[index].pwm_duty_cnt = 0;
-    outputs[index].pwm_period = period;
-    outputs[index].pwm_duty = duty_calc;
-    outputs[index].mode = 1;
-}
-
-//
-void do_set_out(out_t *out, uint8_t val)
-{
-    if (val) {
-        gpio_bits_set(GPIOB, GPIO_PINS_15);
-        gpio_bits_set(out->port, out->pin);
-    }
-    else {
-        gpio_bits_reset(GPIOB, GPIO_PINS_15);
-        gpio_bits_reset(out->port, out->pin);
-    }
-}
-
-//
-void out_as_pwm(void)
-{
-    uint32_t timer_period;
-    uint16_t pwm_pulse;
-    crm_clocks_freq_type crm_clocks_freq_struct = {0};
-    tmr_output_config_type tmr_output_struct;
-    
-    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
-    
-    crm_clocks_freq_get(&crm_clocks_freq_struct);
-    
-    //timer_period = (crm_clocks_freq_struct.sclk_freq / 10 ) - 1;
-    
-    timer_period = 24000 - 1;
-    pwm_pulse = 125*timer_period/1000;
-    
-    tmr_base_init(TMR9, 24000 - 1, 1000 - 1);
-    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
-
-    tmr_output_default_para_init(&tmr_output_struct);
-    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
-    tmr_output_struct.oc_output_state = TRUE;
-    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
-    tmr_output_struct.oc_idle_state = TRUE;
-    
-    tmr_output_channel_config(TMR9, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
-    tmr_channel_value_set(TMR9, TMR_SELECT_CHANNEL_1, pwm_pulse);
-    
-    tmr_flag_clear(TMR9, TMR_OVF_FLAG);
-    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
-    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 5, 0);
-    
-    //tmr_interrupt_enable(TMR9, TMR_OVF_INT, TRUE);
-    tmr_interrupt_enable(TMR9, TMR_C1_INT, TRUE);
-    
-    tmr_counter_enable(TMR9, TRUE);
-}
-
-// Таймер для выходов в режиме PWM. Частота 10Гц.
-void out_pwm_tim_init(void)
-{
-    uint16_t prescaler_value = 0;
-    uint16_t timer_period = 1000 - 1;
-    gpio_init_type gpio_init_struct;
-    
-    gpio_default_para_init(&gpio_init_struct);
-        
-    gpio_init_struct.gpio_pins = GPIO_PINS_15;
-    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
-    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
-    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
-    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
-    gpio_init(GPIOB, &gpio_init_struct);
-
-    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
-    
-    prescaler_value = (uint16_t)(system_core_clock / 10000) - 1;
-    tmr_base_init(TMR9, timer_period, prescaler_value);
-    
-    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
-    tmr_clock_source_div_set(TMR9, TMR_CLOCK_DIV1);
-    
-    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 5, 0);
-
-    tmr_interrupt_enable(TMR9, TMR_OVF_INT, TRUE);
-    
-    tmr_counter_enable(TMR9, TRUE);
-}
-
-
-
-inline void pwm_proc(void)
-{
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        if (outputs[i].mode)    // режим PWM
-        {
-            if (outputs[i].pwm_period_cnt == outputs[i].pwm_period /*PWM_PERIOD_TEST*/) {
-                outputs[i].pwm_period_cnt = 0;
-            }
-            if (outputs[i].pwm_period_cnt == 0) {
-                outputs[i].pwm_flag = false;
-                gpio_bits_set(outputs[i].port, outputs[i].pin);
-                //gpio_bits_set(GPIOB, GPIO_PINS_15);
-            }
-            if (outputs[i].pwm_duty_cnt == outputs[i].pwm_duty /*PWM_DUTY_TEST*/) {
-                outputs[i].pwm_duty_cnt = 0;
-                gpio_bits_reset(outputs[i].port, outputs[i].pin);
-                //gpio_bits_reset(GPIOB, GPIO_PINS_15);
-                outputs[i].pwm_flag = true;
-            }
-            outputs[i].pwm_period_cnt++;
-            if (outputs[i].pwm_flag == false) {
-                outputs[i].pwm_duty_cnt++;
-            }
-        }
-    }
-}
-
-//
-void 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 out_test(void)
-{
-    for (int i = 0; i < DO_NUMBER; i++)
-    {
-        outputs[i].port->odt ^= outputs[i].pin;
-        
-        printf("LOAD_1: %u LOAD_2: %u LOAD_3: %u LOAD_4: %u LOAD_5: %u LOAD_6: %u LOAD_7: %u LOAD_8: %u\r\n", 
-           gpio_input_data_bit_read(load_sens[0].port, load_sens[0].pin),
-           gpio_input_data_bit_read(load_sens[1].port, load_sens[1].pin),
-           gpio_input_data_bit_read(load_sens[2].port, load_sens[2].pin),
-           gpio_input_data_bit_read(load_sens[3].port, load_sens[3].pin),
-           gpio_input_data_bit_read(load_sens[4].port, load_sens[4].pin),
-           gpio_input_data_bit_read(load_sens[5].port, load_sens[5].pin),
-           gpio_input_data_bit_read(load_sens[6].port, load_sens[6].pin), 
-           gpio_input_data_bit_read(load_sens[7].port, load_sens[7].pin));
-        
-        vTaskDelay(500);
-    }  
-}
-
-//
-void load_test(void)
-{
-    printf("LOAD_1: %u LOAD_2: %u LOAD_3: %u LOAD_4: %u LOAD_5: %u LOAD_6: %u LOAD_7: %u LOAD_8: %u\r\n", 
-           gpio_input_data_bit_read(load_sens[0].port, load_sens[0].pin),
-           gpio_input_data_bit_read(load_sens[1].port, load_sens[1].pin),
-           gpio_input_data_bit_read(load_sens[2].port, load_sens[2].pin),
-           gpio_input_data_bit_read(load_sens[3].port, load_sens[3].pin),
-           gpio_input_data_bit_read(load_sens[4].port, load_sens[4].pin),
-           gpio_input_data_bit_read(load_sens[5].port, load_sens[5].pin),
-           gpio_input_data_bit_read(load_sens[6].port, load_sens[6].pin), 
-           gpio_input_data_bit_read(load_sens[7].port, load_sens[7].pin));
-}
-
-
-//
-void TMR1_BRK_TMR9_IRQHandler(void)
-{
-    if(tmr_flag_get(TMR9, TMR_OVF_FLAG) != RESET)
-    {
-        tmr_flag_clear(TMR9, TMR_OVF_FLAG);
-        //GPIOB->odt ^= GPIO_PINS_15;
-        pwm_proc();
-    }
-}
-
-#if 0
-void TMR1_BRK_TMR9_IRQHandler(void)
-{
-    static uint32_t cnt1 = 0;
-    static uint32_t cnt2 = 0;
-    
-    if (tmr_flag_get(TMR9, TMR_OVF_FLAG) != RESET)
-    {
-        tmr_flag_clear(TMR9, TMR_OVF_FLAG);
-        cnt1++;
-        printf("Cnt1 %u\r\n", cnt1);
-    }
-    else if (tmr_flag_get(TMR9, TMR_C1_INT) != RESET)
-    {
-        tmr_flag_clear(TMR9, TMR_C1_INT);
-        cnt2++;
-        printf("Cnt2 %u\r\n", cnt2);
-    }
-}
-#endif
+#include "at32f403a_407.h"
+#include "output.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "settings_api.h"
+#include "io_utils.h"
+#include <stdio.h>
+
+
+out_t outputs[DO_NUMBER] = {
+    {GPIOC, GPIO_PINS_12, 0, 0, 0, false, 0, 0},   // -
+    {GPIOD, GPIO_PINS_2,  0, 0, 0, false, 0, 0},   // -
+    {GPIOE, GPIO_PINS_6,  0, 0, 0, false, 0, 0},   // TMR9_CH2 (remap)
+    {GPIOC, GPIO_PINS_1,  0, 0, 0, false, 0, 0},   // -
+    {GPIOC, GPIO_PINS_11, 0, 0, 0, false, 0, 0},   // -
+    {GPIOD, GPIO_PINS_3,  0, 0, 0, false, 0, 0},   // -
+    {GPIOE, GPIO_PINS_5,  0, 0, 0, false, 0, 0},   // TMR9_CH1 (remap)
+    {GPIOC, GPIO_PINS_2,  0, 0, 0, false, 0, 0}    // -
+};
+
+
+simple_gpio_t load_sens[DO_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}
+};
+
+
+
+//
+void out_gpio_init(out_t *out, uint8_t index)
+{
+    gpio_init_type gpio_init_struct;
+
+    
+    // Выход
+    if (out->mode == 0)
+    {
+        gpio_default_para_init(&gpio_init_struct);
+        
+        gpio_init_struct.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
+        gpio_init_struct.gpio_pull           = GPIO_PULL_NONE;  
+        gpio_init_struct.gpio_mode           = GPIO_MODE_OUTPUT;  
+        gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+        gpio_init_struct.gpio_pins           = out->pin;
+        gpio_init(out->port, &gpio_init_struct); 
+    }
+    
+    do_update(out, index) ;
+}
+
+//
+void do_set_common(void)
+{
+    bool flag = false;
+    
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        // 
+        if ((settings.do_bits & (1 << i)) != (output_state_bit & (1 << i))) {
+            settings.do_bits = output_state_bit;
+            flag = true;
+        } 
+        else if ((settings.do_mode_bits & (1 << i)) != (output_mode_bit & (1 << i))) {
+            settings.do_mode_bits ^= (1 << i);
+            settings.do_mode_bits = output_mode_bit;
+            flag = true;
+        }  
+        else if (settings.do_pwm[i] != output_pwm[i]) {
+            settings.do_pwm[i] = output_pwm[i];
+            flag = true;
+        }
+        else if (settings.do_pwm_save[i] != output_pwm_save[i]) {
+            settings.do_pwm_save[i] = output_pwm_save[i];
+            flag = true;
+        }
+        else if (settings.do_pwm_period [i] != output_pwm_period[i]) {
+            settings.do_pwm_period[i] = output_pwm_period[i];
+            flag = true;
+        }
+        else if (settings.do_pwm_period_save[i] != output_pwm_period_save[i]) {
+            settings.do_pwm_period_save[i] = output_pwm_period_save[i];
+            flag = true;
+        }
+ 
+        if (flag)
+            do_update(&outputs[i], i);
+    }
+}
+
+//
+void do_set(void)
+{
+    if (output_state_bit == settings.do_bits) 
+        return;
+    
+    // Состояние выхода/выходов изменилось
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        if ((settings.do_bits & (1 << i)) != (output_state_bit & (1 << i))) 
+        {
+            do_update(&outputs[i], i);
+        }
+    }
+    
+    // Сохраним новое значение выходов в настройках
+    settings.do_bits = output_state_bit;
+}
+
+// Установка значения на выходе 
+void do_update(out_t *out, uint8_t i)
+{
+    // Режим ШИМ
+    if (settings.do_mode_bits & (1 << i)) {
+        // Безопасный режим включен
+        if (save_mode_get())
+            do_set_pwm(settings.do_pwm_period_save[i], settings.do_pwm_save[i], i);
+        else
+            do_set_pwm(settings.do_pwm_period[i], settings.do_pwm[i], i);
+    }
+    // Режим обычного выхода
+    else {
+        out->mode = 0;
+        // Безопасный режим включен
+        if (save_mode_get())
+            do_set_out(out, settings.do_save_bits & (1 << i));
+        else
+            do_set_out(out, settings.do_bits & (1 << i));
+    }
+}
+
+//
+void do_set_mode(void)
+{
+    if (output_mode_bit == settings.do_mode_bits)
+        return;
+  
+    // Состояние выхода/выходов изменилось
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        if ((settings.do_mode_bits & (1 << i)) != (output_mode_bit & (1 << i)))
+        {
+            settings.do_mode_bits ^= (1 << i);
+            do_update(&outputs[i], i);
+        }
+    }
+  
+    settings.do_mode_bits = output_mode_bit;
+}
+
+//#define PWM_PERIOD_TEST     20
+//#define PWM_DUTY_TEST       10
+void do_set_pwm(uint16_t period, uint16_t duty, uint8_t index)
+{
+    uint16_t duty_calc;
+  
+    if (duty == 0)
+        duty_calc = 0;
+    else
+        duty_calc = (duty*period/100 < 1) ? 1 : duty*period/100;
+    
+    outputs[index].pwm_flag = false;
+    outputs[index].pwm_period_cnt = 0;
+    outputs[index].pwm_duty_cnt = 0;
+    outputs[index].pwm_period = period;
+    outputs[index].pwm_duty = duty_calc;
+    outputs[index].mode = 1;
+}
+
+//
+void do_set_out(out_t *out, uint8_t val)
+{
+    if (val) {
+        gpio_bits_set(GPIOB, GPIO_PINS_15);
+        gpio_bits_set(out->port, out->pin);
+    }
+    else {
+        gpio_bits_reset(GPIOB, GPIO_PINS_15);
+        gpio_bits_reset(out->port, out->pin);
+    }
+}
+
+//
+void out_as_pwm(void)
+{
+    uint32_t timer_period;
+    uint16_t pwm_pulse;
+    crm_clocks_freq_type crm_clocks_freq_struct = {0};
+    tmr_output_config_type tmr_output_struct;
+    
+    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
+    
+    crm_clocks_freq_get(&crm_clocks_freq_struct);
+    
+    //timer_period = (crm_clocks_freq_struct.sclk_freq / 10 ) - 1;
+    
+    timer_period = 24000 - 1;
+    pwm_pulse = 125*timer_period/1000;
+    
+    tmr_base_init(TMR9, 24000 - 1, 1000 - 1);
+    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
+
+    tmr_output_default_para_init(&tmr_output_struct);
+    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
+    tmr_output_struct.oc_output_state = TRUE;
+    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
+    tmr_output_struct.oc_idle_state = TRUE;
+    
+    tmr_output_channel_config(TMR9, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
+    tmr_channel_value_set(TMR9, TMR_SELECT_CHANNEL_1, pwm_pulse);
+    
+    tmr_flag_clear(TMR9, TMR_OVF_FLAG);
+    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
+    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 5, 0);
+    
+    //tmr_interrupt_enable(TMR9, TMR_OVF_INT, TRUE);
+    tmr_interrupt_enable(TMR9, TMR_C1_INT, TRUE);
+    
+    tmr_counter_enable(TMR9, TRUE);
+}
+
+// Таймер для выходов в режиме PWM. Частота 10Гц.
+void out_pwm_tim_init(void)
+{
+    uint16_t prescaler_value = 0;
+    uint16_t timer_period = 1000 - 1;
+    gpio_init_type gpio_init_struct;
+    
+    gpio_default_para_init(&gpio_init_struct);
+        
+    gpio_init_struct.gpio_pins = GPIO_PINS_15;
+    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
+    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
+    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
+    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_init(GPIOB, &gpio_init_struct);
+
+    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
+    
+    prescaler_value = (uint16_t)(system_core_clock / 10000) - 1;
+    tmr_base_init(TMR9, timer_period, prescaler_value);
+    
+    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
+    tmr_clock_source_div_set(TMR9, TMR_CLOCK_DIV1);
+    
+    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 5, 0);
+
+    tmr_interrupt_enable(TMR9, TMR_OVF_INT, TRUE);
+    
+    tmr_counter_enable(TMR9, TRUE);
+}
+
+
+
+inline void pwm_proc(void)
+{
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        if (outputs[i].mode)    // режим PWM
+        {
+            if (outputs[i].pwm_period_cnt == outputs[i].pwm_period /*PWM_PERIOD_TEST*/) {
+                outputs[i].pwm_period_cnt = 0;
+            }
+            if (outputs[i].pwm_period_cnt == 0) {
+                outputs[i].pwm_flag = false;
+                gpio_bits_set(outputs[i].port, outputs[i].pin);
+                //gpio_bits_set(GPIOB, GPIO_PINS_15);
+            }
+            if (outputs[i].pwm_duty_cnt == outputs[i].pwm_duty /*PWM_DUTY_TEST*/) {
+                outputs[i].pwm_duty_cnt = 0;
+                gpio_bits_reset(outputs[i].port, outputs[i].pin);
+                //gpio_bits_reset(GPIOB, GPIO_PINS_15);
+                outputs[i].pwm_flag = true;
+            }
+            outputs[i].pwm_period_cnt++;
+            if (outputs[i].pwm_flag == false) {
+                outputs[i].pwm_duty_cnt++;
+            }
+        }
+    }
+}
+
+//
+void 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 out_test(void)
+{
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        outputs[i].port->odt ^= outputs[i].pin;
+        
+        printf("LOAD_1: %u LOAD_2: %u LOAD_3: %u LOAD_4: %u LOAD_5: %u LOAD_6: %u LOAD_7: %u LOAD_8: %u\r\n", 
+           gpio_input_data_bit_read(load_sens[0].port, load_sens[0].pin),
+           gpio_input_data_bit_read(load_sens[1].port, load_sens[1].pin),
+           gpio_input_data_bit_read(load_sens[2].port, load_sens[2].pin),
+           gpio_input_data_bit_read(load_sens[3].port, load_sens[3].pin),
+           gpio_input_data_bit_read(load_sens[4].port, load_sens[4].pin),
+           gpio_input_data_bit_read(load_sens[5].port, load_sens[5].pin),
+           gpio_input_data_bit_read(load_sens[6].port, load_sens[6].pin), 
+           gpio_input_data_bit_read(load_sens[7].port, load_sens[7].pin));
+        
+        vTaskDelay(500);
+    }  
+}
+
+//
+void load_test(void)
+{
+    printf("LOAD_1: %u LOAD_2: %u LOAD_3: %u LOAD_4: %u LOAD_5: %u LOAD_6: %u LOAD_7: %u LOAD_8: %u\r\n", 
+           gpio_input_data_bit_read(load_sens[0].port, load_sens[0].pin),
+           gpio_input_data_bit_read(load_sens[1].port, load_sens[1].pin),
+           gpio_input_data_bit_read(load_sens[2].port, load_sens[2].pin),
+           gpio_input_data_bit_read(load_sens[3].port, load_sens[3].pin),
+           gpio_input_data_bit_read(load_sens[4].port, load_sens[4].pin),
+           gpio_input_data_bit_read(load_sens[5].port, load_sens[5].pin),
+           gpio_input_data_bit_read(load_sens[6].port, load_sens[6].pin), 
+           gpio_input_data_bit_read(load_sens[7].port, load_sens[7].pin));
+}
+
+
+//
+void TMR1_BRK_TMR9_IRQHandler(void)
+{
+    if(tmr_flag_get(TMR9, TMR_OVF_FLAG) != RESET)
+    {
+        tmr_flag_clear(TMR9, TMR_OVF_FLAG);
+        //GPIOB->odt ^= GPIO_PINS_15;
+        pwm_proc();
+    }
+}
+
+#if 0
+void TMR1_BRK_TMR9_IRQHandler(void)
+{
+    static uint32_t cnt1 = 0;
+    static uint32_t cnt2 = 0;
+    
+    if (tmr_flag_get(TMR9, TMR_OVF_FLAG) != RESET)
+    {
+        tmr_flag_clear(TMR9, TMR_OVF_FLAG);
+        cnt1++;
+        printf("Cnt1 %u\r\n", cnt1);
+    }
+    else if (tmr_flag_get(TMR9, TMR_C1_INT) != RESET)
+    {
+        tmr_flag_clear(TMR9, TMR_C1_INT);
+        cnt2++;
+        printf("Cnt2 %u\r\n", cnt2);
+    }
+}
+#endif

+ 23 - 3
fw/modules/modbus/modbus_params.c

@@ -58,7 +58,7 @@ void mb_init_params(void)
     
     mb_param[index].reg = 0x0100;
 	mb_param[index].size = 1;
-	mb_param[index].param = (uint8_t*)&input_state_bit;  // Текущее состояние входа
+	mb_param[index].param = (uint8_t*)&input_state_bit;  // Текущее состояние входов
 	mb_param[index].set = NULL;
     mb_param[index].get = NULL;
     mb_param[index].check_handler = mb_check_dummy;
@@ -100,13 +100,13 @@ void mb_init_params(void)
     
     index++;
  
-    // Счетчики импульсов. Регистры 0x0102 - 0x0111
+    // Время антидребезга
     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].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;
@@ -114,6 +114,26 @@ void mb_init_params(void)
         addr++;
         index++;
     }
+
+    // Текущее состояние датчиков нагрузки
+    mb_param[index].reg = 0x0130;
+	mb_param[index].size = 1;
+	mb_param[index].param = (uint8_t*)&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*)&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;

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

@@ -12,7 +12,7 @@ extern "C" {
 #endif
 
   
-#define MB_PARAM_MAX			85 //54
+#define MB_PARAM_MAX			87 //54
 
 
 //

+ 55 - 62
fw/user/main.cpp

@@ -66,18 +66,10 @@ int main(void)
 
     delay_init();
 
-    
-    //taskENTER_CRITICAL();      
-            
+                    
     xTaskCreate(init_task, "init_task", 10*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
     
     
-    xTaskCreate(input_task, "input_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
-    
-    xTaskCreate(mux_task, "mux_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
-    
-    
-    
 #if defined (MAI_12)    
     xTaskCreate(adc_task, "adc_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
 #endif
@@ -86,8 +78,7 @@ int main(void)
     xTaskCreate(dac_task, "dac_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
 #endif    
     
-    //taskEXIT_CRITICAL();
-    
+        
     vTaskStartScheduler();
      
     while (1) {}
@@ -128,8 +119,8 @@ void init_task(void *argument)
 // Безопасный режим, входы, выходы
     
     save_mode_init();
-    // TODO Для теста отключаем безопасный режим работы
-    save_mode_set(false);   
+    
+    save_mode_set(true);   
   
     io_port_init();
     
@@ -156,17 +147,20 @@ void init_task(void *argument)
 // Мультиплексор
     
     mux_gpio_init();
-    
-// -------------------------------------------------------------------------- //        
-// Modbus    
-    
-    mb_init();
-    
+    xTaskCreate(mux_task, "mux_task", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
+   
 // -------------------------------------------------------------------------- //            
 // Базовая инициализация входов/выходов
 // TODO потом брать значения из настроек
 
     io_init();
+
+    xTaskCreate(input_task, "input_task", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);
+    
+// -------------------------------------------------------------------------- //        
+// Modbus    
+    
+    mb_init();
     
 // -------------------------------------------------------------------------- //        
 // Сброс счетчика попыток загрузок
@@ -174,47 +168,9 @@ void init_task(void *argument)
     update_reset_boot_try();    
     
 // -------------------------------------------------------------------------- //    
-// Тесты
-    //pwm_test(); // тесы PWM
-    gpio_get_rev();
+// Ревизия платы
     
-// -------------------------------------------------------------------------- //    
-// Сдвиговые регистры и мультиплексоры    
-    //sh_init();
-    
-// Тесты аналоговых входов    
-    //ai_connect_test();
-    //ai_mode_test();
-    //ai_connect_channel(V_ISO);  
-    //ai_connect_channel(AN_INP_1);  
-    //ai_connect_channel(AN_INP_7);  
-    
-// -------------------------------------------------------------------------- //    
-// DAC    
-/*    
-    dac_gpio_init();
-    dac_test(CH_DAC_1, 30000);  
-*/    
-/*    
-    dac_test(CH_DAC_2, 10000);  
-    dac_test(CH_DAC_3, 10000);
-    dac_test(CH_DAC_4, 10000);  
-*/    
-/*    
-    dac_test(CH_DAC_1, 10000);  
-    dac_test(CH_DAC_2, 10000);  
-    dac_test(CH_DAC_3, 10000);
-    dac_test(CH_DAC_4, 10000);  
-*/    
-    
-// -------------------------------------------------------------------------- //    
-// USB (RNDIS class)
-#ifdef USB_RNDIS    
-    usb_clock48m_select(USB_CLK_HEXT);
-    crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);
-    usb_init();
-    usb_eth_init();
-#endif    
+    gpio_get_rev();
     
 // -------------------------------------------------------------------------- //    
 // SPI flash, журнал событий, архив
@@ -245,8 +201,15 @@ void init_task(void *argument)
 // EVENT. Включение питания/перезагрузка.    
     
     log_add_entry(LOG_SYSTEM_BOOT, (log_event_state_t)0, 0, 0);
-
-// -------------------------------------------------------------------------- //  
+   
+// -------------------------------------------------------------------------- //    
+// USB (RNDIS class)
+#ifdef USB_RNDIS    
+    usb_clock48m_select(USB_CLK_HEXT);
+    crm_periph_clock_enable(CRM_USB_PERIPH_CLOCK, TRUE);
+    usb_init();
+    usb_eth_init();
+#endif 
     
 // Удаляем стартовую задачу 
     vTaskDelete(NULL);
@@ -257,7 +220,37 @@ void init_task(void *argument)
     //usb_eth_init();
     //sys_clear();
     //mux_led_test_init();
-
+    //pwm_test();
+    
+    // -------------------------------------------------------------------------- //    
+// Сдвиговые регистры и мультиплексоры    
+    //sh_init();
+    
+// Тесты аналоговых входов    
+    //ai_connect_test();
+    //ai_mode_test();
+    //ai_connect_channel(V_ISO);  
+    //ai_connect_channel(AN_INP_1);  
+    //ai_connect_channel(AN_INP_7);  
+    
+// -------------------------------------------------------------------------- //    
+// DAC    
+/*    
+    dac_gpio_init();
+    dac_test(CH_DAC_1, 30000);  
+*/    
+/*    
+    dac_test(CH_DAC_2, 10000);  
+    dac_test(CH_DAC_3, 10000);
+    dac_test(CH_DAC_4, 10000);  
+*/    
+/*    
+    dac_test(CH_DAC_1, 10000);  
+    dac_test(CH_DAC_2, 10000);  
+    dac_test(CH_DAC_3, 10000);
+    dac_test(CH_DAC_4, 10000);  
+*/  
+    
 #if 0
     // Настройки по умолчанию 
     settings_set_all_default();

BIN
output/fw.bin


Diff do ficheiro suprimidas por serem muito extensas
+ 393 - 434
project/ewarm/iap/iap.dep


Diff do ficheiro suprimidas por serem muito extensas
+ 765 - 786
project/ewarm/module_universal_io.dep


BIN
tools/__pycache__/io_module.cpython-312.pyc


BIN
tools/__pycache__/mb_registers.cpython-312.pyc


BIN
tools/__pycache__/modbus.cpython-312.pyc


+ 122 - 6
tools/digital_io.py

@@ -8,13 +8,13 @@ from time import sleep
 import time
 from datetime import datetime, timedelta, timezone
 from mb_registers import DIO_REGS
-
+from serial import Serial
 
 
 class IO_Digital(IO_Module):
 
-    def __init__(self, tty: str, brate: int, address: int):
-        self.modbus = Modbus(tty, brate, address)
+    def __init__(self, modbus: Modbus):
+        self.modbus = modbus
         super().__init__(self.modbus)
         self.log = DigitalLogReader(self.modbus)
  
@@ -53,6 +53,16 @@ class IO_Digital(IO_Module):
         data = self.modbus.read_holding_registers(DIO_REGS['in_deb_start'] + input - 1, 1)
         return data[0]
 
+    # 0x0130
+    def get_loads_bit(self):
+        data = self.modbus.read_holding_registers(DIO_REGS['load_bits'], 1)
+        return format(data[0], '08b')
+
+    # 0x0131
+    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)
 
@@ -69,10 +79,25 @@ class IO_Digital(IO_Module):
             data = ret[0] & ~(0b1 << (input - 1))
         self.set_inputs_mode(data)
 
+    # 0x0200 - текущее состояние выходов в обычно режиме
+    def set_outputs(self, val):
+        self.modbus.write_holding_register(DIO_REGS['out_cur'], val)
+
+    # Установить значение на конкретном выходе [1..8]
+    def set_output(self, output, val):
+        ret = self.modbus.read_holding_registers(DIO_REGS['out_cur'], 1)
+        if val == 1:
+            data = ret[0] | (0b1 << (output - 1))
+        else:
+            data = ret[0] & ~(0b1 << (output - 1))
+        self.set_outputs(data)
+
+
     def print_inputs(self):
         # Значения входов (битовое поле)
         print('Inputs values [bit field] :', Fore.GREEN + self.get_inputs_bit())
 
+        '''
         # Значение счетчиков
         data = self.get_inputs_counters()
         print('Inputs counters           :', Fore.GREEN + ' | '.join(str(el) for el in data))
@@ -85,16 +110,107 @@ class IO_Digital(IO_Module):
 
          # Период антидребезга (ms)
         print('Debounce input (ms)       :', Fore.GREEN + ' | '.join(str(el) for el in self.get_debounce_channels()))
+        '''
+
+    def print_loads(self):
+        # Значения датчиков нагрузки (битовое поле)
+        print('Loads values [bit field] :', Fore.GREEN + self.get_loads_bit())
+        # Слово достоверности датчиков нагрузки (битовое поле)
+        print('Credibility loads [bit field] :', Fore.GREEN + self.get_cred_bit())
+
+
+class IO_DigitalTester:
+
+    def __init__(self, dev_tester: IO_Digital, dev_dut: IO_Digital):
+        self.tester = dev_tester
+        self.dut = dev_dut
+
+    '''Управление DUT'''
+
+    # Подать/снять питание на DUT
+    def dut_switch(self, state: bool):
+        self.tester.set_output(1, state)
 
+    # Установить 1 на нечетных входах DUT
+    def dut_set_odd_inputs(self):
+        self.tester.set_output(2, False)
+
+    # Установить 1 на четный входах DUT
+    def dut_set_even_imputs(self):
+        self.tester.set_output(2, True)
+
+    '''Тест входов'''
+    def test_inputs(self):
+        self.dut_set_even_imputs()
+        time.sleep(0.1)
+        self.dut.print_inputs()
+        time.sleep(1)
+        self.dut_set_odd_inputs()
+        time.sleep(0.1)
+        self.dut.print_inputs()
+        time.sleep(1)
+
+    '''Тест выходов и датчика обрыва нагрузки'''
+    def test_load(self):
+        # Все выходы DUT разомкнуты
+        print("Все выходы DUT разомкнуты...")
+        self.dut.set_outputs(0)
+        self.dut.print_loads()
+        time.sleep(0.1)
+        # Замкнуть все выходы DUT (лампочка должна гореть)
+        print("Все выходы DUT замкнуты...")
+        self.dut.set_outputs(0b11111111)
+        time.sleep(0.1)
+        
+        for i in range(1, 9):
+            # Разомкнуть i-ый выход DUT
+            print(f"Разомкнуть выход {i}")
+            self.dut.set_output(i, 0)
+            time.sleep(1)
+            self.dut.print_loads()
+            self.dut.set_output(i, 1)
+            time.sleep(1)
+
+    def get_load(self):
+        self.dut.set_outputs(0b11110111)
+        # self.dut.set_outputs(0)
+        time.sleep(1)
+        self.dut.print_loads()
 
 
 def main():
     colorama.init(autoreset=True)
-    dev = IO_Digital('COM24', 115200, 15)
-    dev.modbus.MB_DEBUG = False
+    
+    serial_port = Serial('COM24', 115200, timeout=0.05, parity='N', xonxoff=False)
+    
+    modbus_tester = Modbus(serial_port, 1)
+    dev_tester = IO_Digital(modbus_tester)
+
+    modbus_dut = Modbus(serial_port, 2)
+    dev_dut = IO_Digital(modbus_dut)
+
+    tester = IO_DigitalTester(dev_tester, dev_dut)
+
+    '''Включить DUT'''
+    tester.dut_switch(True)
+
+    '''Запросить системные настройки DUT'''
+    # dev_dut.sys.get_system_vars()
+
+    '''Тест входов. Переключение значений на входах DUT'''
+    # for i in range(10):
+    #     tester.test_inputs()
+
+    '''Тестирование выходов и датчиков обрыва нагрузки'''
+    # tester.test_load()
+    for i in range(100):
+        tester.get_load()
+
+
+
 
     '''Системные переменные и параметры'''
-    dev.sys.get_system_vars()
+    # dev_tester.sys.get_system_vars()
 
     ''' Установить текущее время с учетом часового пояса'''
     # dev.sys.set_rtc()     

+ 0 - 12
tools/io_module.py

@@ -30,18 +30,6 @@ class IO_Module:
         data = self.read_holding_registers(reg_table['out_cur'], 1)
         return format(data[0], '08b')
 
-    # 0x0200 - текущее состояние выходов в обычно режиме
-    def set_outputs(self, val):
-        self.write_holding_register(reg_table['out_cur'], val)
-
-    def set_output(self, output, val):
-        ret = self.read_holding_registers(reg_table['out_cur'], 1)
-        if val == 1:
-            data = ret[0] | (0b1 << (output - 1))
-        else:
-            data = ret[0] & ~(0b1 << (output - 1))
-        self.set_outputs(data)
-
     # 0x0202 - режим работы выходов; 0 - обычный, 1 - ШИМ
     def get_outputs_mode(self):
         data = self.read_holding_registers(reg_table['out_mode'], 1)

+ 2 - 1
tools/mb_registers.py

@@ -7,6 +7,7 @@ reg_table = {'out_cur': 0x0200, 'out_mode': 0x0202, 'out_mode_save': 0x0203, 'pw
              'test_status': 0x0089, 'password': 0x008A, 'save_sys_settings': 0x008B}
 
 
-DIO_REGS = {'in_bits': 0x0100, 'in_cnt': 0x0102,'in_mode': 0x0120, 'in_norm': 0x0122, 'in_deb_start': 0x124}
+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}
 
 LOG_REGS = {'log_info': 0x0900, 'log_ent': 0x0901, 'arch_cap': 0x0902, 'arch_ent': 0x0903, 'arch_per': 0x0904}

+ 3 - 2
tools/modbus.py

@@ -55,8 +55,9 @@ class Modbus(ModbusMixin):
     MB_DEBUG: bool = False
     MB_TRIES: int = 3
 
-    def __init__(self, tty: str, brate: int, address: int):
-        self.serial = Serial(port=tty, baudrate=brate, timeout=0.05, parity='N', xonxoff=False)
+    # def __init__(self, tty: str, brate: int, address: int):
+    def __init__(self, serial: Serial, address: int):
+        self.serial = serial
         self.address = address
 
     @classmethod

+ 16 - 0
tools/serial_port.py

@@ -0,0 +1,16 @@
+from serial import Serial
+import time
+
+class SerialPort:
+    
+    def __init__(self):
+        pass
+
+
+
+def main():
+    pass
+
+
+if __name__ == '__main__':
+    main()

+ 1 - 0
tools/tester.py

@@ -1,3 +1,4 @@
+import digital_io
 
 
 class Tester:

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff