Browse Source

Входы/выходы. Добавляю индикацию.

TelenkovDmitry 1 year ago
parent
commit
c07ec7d573

BIN
doc/0482601_SCH_202403028_1217.pdf


+ 87 - 33
fw/modules/io/input.c

@@ -3,19 +3,20 @@
 #include "settings_api.h"
 #include "FreeRTOS.h"
 #include "task.h"
+#include "mux.h"
 #include <stdio.h>
 
 
 // *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
 din_t inputs[DI_NUMBER] = {
-    {GPIOB, GPIO_PINS_11, 0, 0, false, 0}, // 1   
-    {GPIOB, GPIO_PINS_10, 0, 0, false, 0}, // 2
-    {GPIOE, GPIO_PINS_14, 0, 0, false, 0}, // 3 перенесли {GPIOB, GPIO_PINS_1,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE1,  0},
-    {GPIOE, GPIO_PINS_15, 0, 0, false, 0}, // 4 перенесли {GPIOB, GPIO_PINS_0,  1, GPIO_PORT_SOURCE_GPIOB, GPIO_PINS_SOURCE0,  0},
-    {GPIOA, GPIO_PINS_3,  0, 0, false, 0}, // 5
-    {GPIOA, GPIO_PINS_2,  0, 0, false, 0}, // 6
-    {GPIOA, GPIO_PINS_1,  0, 0, false, 0}, // 7
-    {GPIOA, GPIO_PINS_0,  0, 0, false, 0}  // 8
+    {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
 };
 
 
@@ -31,7 +32,7 @@ void in_init(din_t *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);
-        
+
 #if 0    
     // Вход
     if (input->mode == 0)
@@ -73,7 +74,7 @@ void in_exint_init(void)
                                     EXINT_LINE_3 | EXINT_LINE_10 | 
                                     EXINT_LINE_11| EXINT_LINE_14 | EXINT_LINE_15; 
     
-    exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
+    exint_init_struct.line_polarity = EXINT_TRIGGER_BOTH_EDGE;
     exint_init(&exint_init_struct);
     
     exint_flag_clear(EXINT_LINE_0);
@@ -148,10 +149,14 @@ void input_task(void *params)
             {
                 input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
                 
-                if (!input_state[i])
+                if (!input_state[i]) {
                     input_state_bit &= ~(1 << i); // снять бит
-                else
+                    leds[i].state = LED_OFF;
+                }
+                else {
                     input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
             }
         }
             
@@ -171,10 +176,14 @@ inline void debounce(void)
                 
                 input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
                 
-                if (!input_state[i])
+                if (!input_state[i]) {
                     input_state_bit &= ~(1 << i); // снять бит
-                else
+                    leds[i].state = LED_OFF;
+                }
+                else {
                     input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
             }
         }
     }
@@ -188,8 +197,14 @@ void EXINT0_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_0);
         if (inputs[7].mode == 0)
             inputs[7].p_flag = true;
-        else
-            input_cnt[7]++;
+        else { 
+            if (inputs[7].cnt_flag) {
+                input_cnt[7]++;
+                inputs[7].cnt_flag = false;
+            }
+            else
+                inputs[7].cnt_flag = true;
+        }
     }
 }
 
@@ -201,8 +216,14 @@ void EXINT1_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_1);
         if (inputs[6].mode == 0)
             inputs[6].p_flag = true;
-        else
-            input_cnt[6]++;
+        else { 
+            if (inputs[6].cnt_flag) {
+                input_cnt[6]++;
+                inputs[6].cnt_flag = false;
+            }
+            else
+                inputs[6].cnt_flag = true;
+        }
     }
 }
 
@@ -214,9 +235,14 @@ void EXINT2_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_2);
         if (inputs[5].mode == 0)
             inputs[5].p_flag = true;
-        else
-            input_cnt[5]++;
-        
+        else { 
+            if (inputs[5].cnt_flag) {
+                input_cnt[5]++;
+                inputs[5].cnt_flag = false;
+            }
+            else
+                inputs[5].cnt_flag = true;
+        }
     }
 }
 
@@ -228,8 +254,14 @@ void EXINT3_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_3);
         if (inputs[4].mode == 0)
             inputs[4].p_flag = true;
-        else
-            input_cnt[4]++;
+        else { 
+            if (inputs[4].cnt_flag) {
+                input_cnt[4]++;
+                inputs[4].cnt_flag = false;
+            }
+            else
+                inputs[4].cnt_flag = true;
+        }
     }
 }
 
@@ -242,9 +274,14 @@ void EXINT15_10_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_10);
         if (inputs[1].mode == 0)
             inputs[1].p_flag = true;
-        else
-            input_cnt[1]++;
-          
+        else { 
+            if (inputs[1].cnt_flag) {
+                input_cnt[1]++;
+                inputs[1].cnt_flag = false;
+            }
+            else
+                inputs[1].cnt_flag = true;
+        }
     }
     // IN_1 GPIOB_11
     else if (exint_flag_get(EXINT_LINE_11) != RESET)  
@@ -252,8 +289,14 @@ void EXINT15_10_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_11);
         if (inputs[0].mode == 0)
             inputs[0].p_flag = true;
-        else
-            input_cnt[0]++;
+        else { 
+            if (inputs[0].cnt_flag) {
+                input_cnt[0]++;
+                inputs[0].cnt_flag = false;
+            }
+            else
+                inputs[0].cnt_flag = true;
+        }
     }
     // IN_3 GPIOE_14
     else if (exint_flag_get(EXINT_LINE_14) != RESET)  
@@ -261,9 +304,14 @@ void EXINT15_10_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_14);
         if (inputs[2].mode == 0)
             inputs[2].p_flag = true;
-        else
-            input_cnt[2]++;
-        
+        else { 
+            if (inputs[2].cnt_flag) {
+                input_cnt[2]++;
+                inputs[2].cnt_flag = false;
+            }
+            else
+                inputs[2].cnt_flag = true;
+        }
     }
     // IN_4 GPIOE_15
     else if (exint_flag_get(EXINT_LINE_15) != RESET) 
@@ -271,7 +319,13 @@ void EXINT15_10_IRQHandler(void)
         exint_flag_clear(EXINT_LINE_15);
         if (inputs[3].mode == 0)
             inputs[3].p_flag = true;
-        else
-            input_cnt[3]++;
+        else { 
+            if (inputs[3].cnt_flag) {
+                input_cnt[3]++;
+                inputs[3].cnt_flag = false;
+            }
+            else
+                inputs[3].cnt_flag = true;
+        }
     }    
 }

+ 2 - 1
fw/modules/io/io.h

@@ -53,8 +53,9 @@ typedef struct
     uint16_t pin;
     uint16_t mode;  // 0 - обычный вход, 1 - счетный вход
     uint32_t deb_counter;
-    bool p_flag;
     uint32_t cnt;
+    bool p_flag;
+    bool cnt_flag;
     
 } din_t;
 

+ 6 - 6
fw/modules/io/mux.c

@@ -11,6 +11,11 @@ mux_channel_t leds[LED_NUMBER] = {
                                   {INP_3, {0, 0, 0}, LED_OFF, 0},
                                   {INP_4, {0, 0, 0}, LED_OFF, 0},
 
+                                  {INP_5, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_6, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_7, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_8, {0, 1, 1}, LED_OFF, 0},
+                                  
                                   {OUT_1_G, {1, 0, 0}, LED_OFF, 0},
                                   {OUT_2_G, {1, 0, 0}, LED_OFF, 0},
                                   {OUT_3_G, {1, 0, 0}, LED_OFF, 0},
@@ -34,12 +39,7 @@ mux_channel_t leds[LED_NUMBER] = {
                                   {OUT_5_G, {1, 0, 1}, LED_OFF, 0},
                                   {OUT_6_G, {1, 0, 1}, LED_OFF, 0},
                                   {OUT_7_G, {1, 0, 1}, LED_OFF, 0},
-                                  {OUT_8_G, {1, 0, 1}, LED_OFF, 0},
-                                  
-                                  {INP_5, {0, 1, 1}, LED_OFF, 0},
-                                  {INP_6, {0, 1, 1}, LED_OFF, 0},
-                                  {INP_7, {0, 1, 1}, LED_OFF, 0},
-                                  {INP_8, {0, 1, 1}, LED_OFF, 0}
+                                  {OUT_8_G, {1, 0, 1}, LED_OFF, 0}
                                  };
 
 

+ 6 - 6
fw/modules/io/mux.h

@@ -33,7 +33,12 @@ typedef enum
     INP_1 = 0, 
     INP_2, 
     INP_3, 
-    INP_4, 
+    INP_4,
+    
+    INP_5, 
+    INP_6, 
+    INP_7, 
+    INP_8,
     
     OUT_1_G,
     OUT_2_G,
@@ -59,11 +64,6 @@ typedef enum
     OUT_6_G,
     OUT_7_G,
     OUT_8_G,
-    
-    INP_5, 
-    INP_6, 
-    INP_7, 
-    INP_8,
       
 } led_t;
 

+ 331 - 0
iap/modules/io/input.c

@@ -0,0 +1,331 @@
+#include "at32f403a_407.h"
+#include "input.h"
+#include "settings_api.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "mux.h"
+#include <stdio.h>
+
+
+// *port; pin; mode; port_source; pin_source; deb_counter; p_flag; cnt;
+din_t 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
+};
+
+
+//
+void in_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);
+
+#if 0    
+    // Вход
+    if (input->mode == 0)
+    {
+        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); 
+    }
+    // Счетный вход
+    else if (input->mode == 1)
+    {
+    }
+#endif
+}
+
+//
+void in_exint_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);
+}
+
+//
+void in_set(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if ((settings.di_mode_bits & (1 << i)) != inputs[i].mode) 
+        {
+            inputs[i].mode = settings.di_mode_bits & (1 << i);
+            if (inputs[i].mode == 0) 
+            {
+                inputs[i].cnt = 0;
+                inputs[i].p_flag = false;
+                input_cnt[i] = 0;
+            }
+            else
+            {
+                input_state_bit &= ~(1 << i);
+            }
+        }
+    }
+}
+
+//
+void io_test(void)
+{
+#if 0  
+    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
+           gpio_input_data_bit_read(inputs[0].port, inputs[0].pin),
+           gpio_input_data_bit_read(inputs[1].port, inputs[1].pin),
+           gpio_input_data_bit_read(inputs[2].port, inputs[2].pin),
+           gpio_input_data_bit_read(inputs[3].port, inputs[3].pin),
+           gpio_input_data_bit_read(inputs[4].port, inputs[4].pin),
+           gpio_input_data_bit_read(inputs[5].port, inputs[5].pin),
+           gpio_input_data_bit_read(inputs[6].port, inputs[6].pin), 
+           gpio_input_data_bit_read(inputs[7].port, inputs[7].pin));
+#endif    
+    
+    printf("IN_1: %u IN_2: %u IN_3: %u IN_4: %u IN_5: %u IN_6: %u IN_7: %u IN_8: %u\r\n", 
+           input_cnt[0], input_cnt[1], input_cnt[2], input_cnt[3], 
+           input_cnt[4], input_cnt[5], input_cnt[6], input_cnt[7]);
+    
+}
+
+//
+void input_task(void *params)
+{
+    for (;;)
+    {
+        
+        for (int i = 0; i < DI_NUMBER; i++)
+        {
+            // Режим обычного входа
+            if (inputs[i].mode == 0)
+            {
+                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
+                
+                if (!input_state[i]) {
+                    input_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+            
+        vTaskDelay(100);
+    }
+}
+
+//
+inline void debounce(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        if ((inputs[i].p_flag) && (inputs[i].mode == 0)){
+            if (++inputs[i].cnt == settings.di_debounce[i]) {
+                inputs[i].cnt = 0;
+                inputs[i].p_flag = false;
+                
+                input_state[i] = (uint16_t)gpio_input_data_bit_read(inputs[i].port, inputs[i].pin);
+                
+                if (!input_state[i]) {
+                    input_state_bit &= ~(1 << i); // снять бит
+                    leds[i].state = LED_OFF;
+                }
+                else {
+                    input_state_bit |= input_state[i] << i;
+                    leds[i].state = LED_ON;
+                }
+            }
+        }
+    }
+}
+
+// IN_8 GPIOA_0
+void EXINT0_IRQHandler(void)
+{
+    if (exint_flag_get(EXINT_LINE_0) != RESET) 
+    {
+        exint_flag_clear(EXINT_LINE_0);
+        if (inputs[7].mode == 0)
+            inputs[7].p_flag = true;
+        else { 
+            if (inputs[7].cnt_flag) {
+                input_cnt[7]++;
+                inputs[7].cnt_flag = false;
+            }
+            else
+                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 (inputs[6].mode == 0)
+            inputs[6].p_flag = true;
+        else { 
+            if (inputs[6].cnt_flag) {
+                input_cnt[6]++;
+                inputs[6].cnt_flag = false;
+            }
+            else
+                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 (inputs[5].mode == 0)
+            inputs[5].p_flag = true;
+        else { 
+            if (inputs[5].cnt_flag) {
+                input_cnt[5]++;
+                inputs[5].cnt_flag = false;
+            }
+            else
+                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 (inputs[4].mode == 0)
+            inputs[4].p_flag = true;
+        else { 
+            if (inputs[4].cnt_flag) {
+                input_cnt[4]++;
+                inputs[4].cnt_flag = false;
+            }
+            else
+                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 (inputs[1].mode == 0)
+            inputs[1].p_flag = true;
+        else { 
+            if (inputs[1].cnt_flag) {
+                input_cnt[1]++;
+                inputs[1].cnt_flag = false;
+            }
+            else
+                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 (inputs[0].mode == 0)
+            inputs[0].p_flag = true;
+        else { 
+            if (inputs[0].cnt_flag) {
+                input_cnt[0]++;
+                inputs[0].cnt_flag = false;
+            }
+            else
+                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 (inputs[2].mode == 0)
+            inputs[2].p_flag = true;
+        else { 
+            if (inputs[2].cnt_flag) {
+                input_cnt[2]++;
+                inputs[2].cnt_flag = false;
+            }
+            else
+                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 (inputs[3].mode == 0)
+            inputs[3].p_flag = true;
+        else { 
+            if (inputs[3].cnt_flag) {
+                input_cnt[3]++;
+                inputs[3].cnt_flag = false;
+            }
+            else
+                inputs[3].cnt_flag = true;
+        }
+    }    
+}

+ 30 - 0
iap/modules/io/input.h

@@ -0,0 +1,30 @@
+#ifndef __INPUT_H
+#define __INPUT_H
+
+
+#include "io.h"
+
+
+extern din_t inputs[];
+
+//
+void in_init(din_t *input);
+
+//
+void in_exint_init(void);
+
+//
+void in_set(void);
+
+//
+void io_test(void);
+
+//
+void input_task(void *params);
+
+//
+void debounce(void);
+
+
+#endif  // __INPUT_H
+

+ 128 - 0
iap/modules/io/io.c

@@ -0,0 +1,128 @@
+#include "at32f403a_407.h"
+#include "io.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "input.h"
+#include "output.h"
+#include "settings_api.h"
+#include "io_utils.h"
+#include <stdio.h>
+
+
+uint16_t input_state[DI_NUMBER];     // состояние входа
+uint16_t input_state_bit;
+
+
+//uint16_t output_state[DO_NUMBER];     // состояние входа
+uint16_t output_state_bit;
+uint16_t output_mode_bit;
+uint16_t output_pwm[DO_NUMBER];
+uint16_t output_pwm_save[DO_NUMBER];
+uint16_t output_pwm_period[DO_NUMBER];
+uint16_t output_pwm_period_save[DO_NUMBER];
+
+// -------------------------------------------------------------------------- //
+// Текущие параметры
+
+//uint16_t input_state[DI_NUMBER];     // состояние входа
+uint32_t input_cnt[DI_NUMBER];       // счетчики входов
+
+
+//
+void io_port_init(void)
+{
+    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
+    
+    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
+    
+    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
+    pwc_battery_powered_domain_access(TRUE);
+    
+    io_tim_init();
+}
+
+//
+void io_init(void)
+{
+    for (int i = 0; i < DI_NUMBER; i++)
+    {
+        in_init(&inputs[i]);
+    }
+
+    output_state_bit = settings.do_bits;
+    output_mode_bit = settings.do_mode_bits;
+    
+    // Таймер для выходов в режиме PWM
+    out_pwm_tim_init();
+    
+    for (int i = 0; i < DO_NUMBER; i++)
+    {
+        output_pwm[i] = settings.do_pwm[i];
+        output_pwm_save[i] = settings.do_pwm_save[i];
+        output_pwm_period[i] = settings.do_pwm_period[i];
+        output_pwm_period_save[i] = settings.do_pwm_period_save[i];
+
+        if (save_mode_get()) {
+            outputs[i].pwm_duty = settings.do_pwm_save[i];
+            outputs[i].pwm_period = settings.do_pwm_period_save[i];
+        }
+        else {
+            outputs[i].pwm_duty = settings.do_pwm[i];
+            outputs[i].pwm_period = settings.do_pwm_period[i];
+        }
+        
+        out_gpio_init(&outputs[i], i);
+        load_sens_init(&load_sens[i]);
+    }
+}
+
+// Таймер для антидребезга
+void io_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);  
+}
+
+
+void TMR8_BRK_TMR12_IRQHandler(void)
+{
+    //static int i = 0;
+    //static int cnt = 0;
+
+    if(tmr_flag_get(TMR12, TMR_OVF_FLAG) != RESET)
+    {
+        tmr_flag_clear(TMR12, TMR_OVF_FLAG);
+
+        debounce();
+#if 0        
+        if (i++ == 1000) {
+            i = 0;
+            cnt++;
+            printf("CNT: %u\r\n");
+        }
+#endif        
+    }
+}
+

+ 140 - 0
iap/modules/io/io.h

@@ -0,0 +1,140 @@
+#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
+

+ 46 - 0
iap/modules/io/io_utils.c

@@ -0,0 +1,46 @@
+#include "at32f403a_407.h"
+#include "io_utils.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include "input.h"
+#include "output.h"
+#include "settings_api.h"
+#include "mux.h"
+#include <stdio.h>
+
+
+bool save_mode = false;
+static uint16_t counter = 0;
+
+//
+void save_mode_init(void)
+{
+    save_mode = settings.save_mode;
+    save_mode ? mux_led_status(false) : mux_led_status(true);
+}
+
+//
+void save_mode_set(bool state)
+{
+    save_mode = state;
+    save_mode ? mux_led_status(false) : mux_led_status(true);
+}
+
+//
+bool save_mode_get(void)
+{
+    return save_mode;
+}
+
+// Должна вызываться раз в секунду
+void save_mode_inc_cnt(void)
+{
+    bool foo = counter++ > settings.save_delay ? true : false;
+    save_mode_set(foo);
+}
+
+//
+void save_mode_reset_cnt(void)
+{
+    counter = 0;
+}

+ 23 - 0
iap/modules/io/io_utils.h

@@ -0,0 +1,23 @@
+#ifndef __IO_UTILS_H
+#define __IO_UTILS_H
+
+#include <stdbool.h>
+
+
+//
+void save_mode_init(void);
+
+//
+void save_mode_set(bool state);
+
+//
+bool save_mode_get(void);
+
+//
+void save_mode_inc_cnt(void);
+
+//
+void save_mode_reset_cnt(void);
+
+#endif  // __IO_UTILS_H
+

+ 174 - 0
iap/modules/io/mux.c

@@ -0,0 +1,174 @@
+#include "at32f403a_407.h"
+#include "mux.h"
+#include "FreeRTOS.h"
+#include "task.h"
+#include <stdbool.h>
+
+
+mux_channel_t leds[LED_NUMBER] = {
+                                  {INP_1, {0, 0, 0}, LED_OFF, 0},
+                                  {INP_2, {0, 0, 0}, LED_OFF, 0},
+                                  {INP_3, {0, 0, 0}, LED_OFF, 0},
+                                  {INP_4, {0, 0, 0}, LED_OFF, 0},
+
+                                  {INP_5, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_6, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_7, {0, 1, 1}, LED_OFF, 0},
+                                  {INP_8, {0, 1, 1}, LED_OFF, 0},
+                                  
+                                  {OUT_1_G, {1, 0, 0}, LED_OFF, 0},
+                                  {OUT_2_G, {1, 0, 0}, LED_OFF, 0},
+                                  {OUT_3_G, {1, 0, 0}, LED_OFF, 0},
+                                  {OUT_4_G, {1, 0, 0}, LED_OFF, 0},
+                                  
+                                  {OUT_1_R, {0, 1, 0}, LED_OFF, 0},
+                                  {OUT_2_R, {0, 1, 0}, LED_OFF, 0},
+                                  {OUT_3_R, {0, 1, 0}, LED_OFF, 0},
+                                  {OUT_4_R, {0, 1, 0}, LED_OFF, 0},
+
+                                  {STATUS_G, {1, 1, 0}, LED_OFF, 0},
+                                  {STATUS_R, {1, 1, 0}, LED_OFF, 0},
+                                  {RX_G, {1, 1, 0}, LED_OFF, 0},
+                                  {TX_R, {1, 1, 0}, LED_OFF, 0},
+                                  
+                                  {OUT_5_R, {0, 0, 1}, LED_OFF, 0},
+                                  {OUT_6_R, {0, 0, 1}, LED_OFF, 0},
+                                  {OUT_7_R, {0, 0, 1}, LED_OFF, 0},
+                                  {OUT_8_R, {0, 0, 1}, LED_OFF, 0},
+
+                                  {OUT_5_G, {1, 0, 1}, LED_OFF, 0},
+                                  {OUT_6_G, {1, 0, 1}, LED_OFF, 0},
+                                  {OUT_7_G, {1, 0, 1}, LED_OFF, 0},
+                                  {OUT_8_G, {1, 0, 1}, LED_OFF, 0}
+                                 };
+
+
+
+//
+void mux_led_init(mux_channel_t *ch)
+{
+}
+
+
+//
+void mux_gpio_init(void)
+{
+    gpio_init_type gpio_initstructure;
+  
+    
+    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_GPIOE_PERIPH_CLOCK, TRUE);
+    
+    // LED_COL
+    //      COL_1 - PD6
+    //      COL_2 - PD7
+    //      COL_3 - PB6
+    //      COL_4 - PB7
+    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
+    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
+    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_initstructure.gpio_pins           = GPIO_PINS_6 | GPIO_PINS_7;
+    gpio_init(GPIOB, &gpio_initstructure); 
+
+    gpio_initstructure.gpio_pins           = GPIO_PINS_6 | GPIO_PINS_7;
+    gpio_init(GPIOD, &gpio_initstructure); 
+    
+    gpio_bits_reset(GPIOB, GPIO_PINS_6 | GPIO_PINS_7);
+    gpio_bits_reset(GPIOD, GPIO_PINS_6 | GPIO_PINS_7);
+    
+    // LED_LINE (низкий уровень на пине = высокий уровень на входе MUX)
+    //      LINE_0 - PE3
+    //      LINE_1 - PE2
+    //      LINE_2 - PB9
+    gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_PUSH_PULL;  
+    gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;  
+    gpio_initstructure.gpio_mode           = GPIO_MODE_OUTPUT;  
+    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
+    gpio_initstructure.gpio_pins           = GPIO_PINS_2 | GPIO_PINS_3;
+    gpio_init(GPIOE, &gpio_initstructure); 
+
+    gpio_initstructure.gpio_pins           = GPIO_PINS_9;
+    gpio_init(GPIOB, &gpio_initstructure);
+    
+    gpio_bits_reset(GPIOE, GPIO_PINS_2 | GPIO_PINS_3);
+    gpio_bits_reset(GPIOB, GPIO_PINS_9);
+}
+
+
+//
+void mux_led_proc(void)
+{
+    uint8_t shift = 0;
+    
+    for (uint8_t i = 0; i < LED_NUMBER/4; i++)
+    {
+        leds[shift].line[0] ? (LINE_0_RESET) : (LINE_0_SET);
+        leds[shift].line[1] ? (LINE_1_RESET) : (LINE_1_SET);
+        leds[shift].line[2] ? (LINE_2_RESET) : (LINE_2_SET);
+        
+        leds[i*4].state     == LED_ON ? (COL_1_SET) : (COL_1_RESET);
+        leds[i*4 + 1].state == LED_ON ? (COL_2_SET) : (COL_2_RESET);
+        leds[i*4 + 2].state == LED_ON ? (COL_3_SET) : (COL_3_RESET);
+        leds[i*4 + 3].state == LED_ON ? (COL_4_SET) : (COL_4_RESET);
+        
+        if (leds[i*4].state == LED_ON || leds[i*4 + 1].state == LED_ON || 
+            leds[i*4 + 2].state == LED_ON || leds[i*4 + 3].state == LED_ON) 
+        {
+            vTaskDelay(1);
+        }
+        
+        shift += 4;
+    }
+}
+
+//
+void mux_led_test_init(void)
+{
+    LINE_0_SET;
+    LINE_1_SET;
+    LINE_2_SET;
+}
+
+//
+void mux_led_test_toggle(void)
+{
+    static bool flag = false;
+    
+    if (!flag) {
+        COL_1_SET;
+        flag = true;
+    }
+    else {
+        COL_1_RESET;
+        flag = false;
+    }
+}
+
+//
+void mux_led_blink(void)
+{
+    for (int i = 0; i < LED_NUMBER; i++)
+    {
+        leds[i].state = LED_ON;
+        
+        vTaskDelay(100);
+        
+        leds[i].state = LED_OFF;
+    }
+}
+
+// true - normal
+// false - alarm
+void mux_led_status(bool state)
+{
+    if (state) {
+        leds[STATUS_G].state = LED_ON;
+        leds[STATUS_R].state = LED_OFF;
+    }
+    else {
+        leds[STATUS_G].state = LED_OFF;
+        leds[STATUS_R].state = LED_ON;
+    }
+}

+ 115 - 0
iap/modules/io/mux.h

@@ -0,0 +1,115 @@
+#ifndef __MUX_H
+#define __MUX_H
+
+#include <stdbool.h>
+
+//
+#define LED_NUMBER      28
+
+#define LINE_0_SET      GPIOE->scr = GPIO_PINS_3
+#define LINE_0_RESET    GPIOE->clr = GPIO_PINS_3
+
+#define LINE_1_SET      GPIOE->scr = GPIO_PINS_2
+#define LINE_1_RESET    GPIOE->clr = GPIO_PINS_2
+
+#define LINE_2_SET      GPIOB->scr = GPIO_PINS_9
+#define LINE_2_RESET    GPIOB->clr = GPIO_PINS_9
+
+#define COL_1_SET      GPIOD->scr = GPIO_PINS_6
+#define COL_1_RESET    GPIOD->clr = GPIO_PINS_6
+
+#define COL_2_SET      GPIOD->scr = GPIO_PINS_7
+#define COL_2_RESET    GPIOD->clr = GPIO_PINS_7
+
+#define COL_3_SET      GPIOB->scr = GPIO_PINS_6
+#define COL_3_RESET    GPIOB->clr = GPIO_PINS_6
+
+#define COL_4_SET      GPIOB->scr = GPIO_PINS_7
+#define COL_4_RESET    GPIOB->clr = GPIO_PINS_7
+
+
+typedef enum
+{
+    INP_1 = 0, 
+    INP_2, 
+    INP_3, 
+    INP_4,
+    
+    INP_5, 
+    INP_6, 
+    INP_7, 
+    INP_8,
+    
+    OUT_1_G,
+    OUT_2_G,
+    OUT_3_G,
+    OUT_4_G,
+    
+    OUT_1_R,
+    OUT_2_R,
+    OUT_3_R,
+    OUT_4_R,
+    
+    STATUS_G,
+    STATUS_R,
+    RX_G,
+    TX_R,
+    
+    OUT_5_R,
+    OUT_6_R,
+    OUT_7_R,
+    OUT_8_R,
+    
+    OUT_5_G,
+    OUT_6_G,
+    OUT_7_G,
+    OUT_8_G,
+      
+} led_t;
+
+
+typedef enum
+{
+    LED_OFF = 0, 
+    LED_ON,
+    LED_BLINK,
+    
+} led_state_t;
+
+
+typedef struct 
+{
+    led_t           name;
+    uint8_t         line[3];    // [line_0, line_1, line_2]
+    led_state_t     state;
+    uint32_t        cnt;
+    
+} mux_channel_t;
+
+
+//
+void mux_led_init(mux_channel_t *ch);
+
+//
+void mux_gpio_init(void);
+
+//
+void mux_led_proc(void);
+
+//
+void mux_led_blink(void);
+
+//
+void mux_led_test_init(void);
+
+//
+void mux_led_test_toggle(void);
+
+//
+void mux_led_status(bool state);
+
+
+extern mux_channel_t leds[];
+
+#endif  // __MUX_H
+

+ 369 - 0
iap/modules/io/output.c

@@ -0,0 +1,369 @@
+#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

+ 58 - 0
iap/modules/io/output.h

@@ -0,0 +1,58 @@
+#ifndef __OUTPUT_H
+#define __OUTPUT_H
+
+
+#include "io.h"
+
+
+#define PWM_PERIOD_TEST     20
+#define PWM_DUTY_TEST       18
+
+
+extern out_t outputs[];
+
+extern simple_gpio_t load_sens[];
+
+
+//
+void out_gpio_init(out_t *out, uint8_t index);
+
+//
+void do_set_common(void);
+
+//
+void do_set(void);
+
+// Установка значения на выходе 
+void do_update(out_t *out, uint8_t index);
+
+//
+void do_set_mode(void);
+
+//
+void do_set_pwm(uint16_t period, uint16_t duty, uint8_t index);
+
+//
+void do_set_out(out_t *out, uint8_t val);
+
+// 
+void out_pwm_tim_init(void);
+
+//
+void out_as_pwm(void);
+
+//
+void pwm_proc(void);
+
+//
+void load_sens_init(simple_gpio_t *sens);
+
+//
+void out_test(void);
+
+//
+void load_test(void);
+
+
+#endif  // __OUTPUT_H
+

BIN
output/fw.bin


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


+ 7 - 0
project/ewarm/iap/iap.ewp

@@ -373,6 +373,7 @@
                     <state>$PROJ_DIR$\..\..\..\iap\modules\modbus</state>
                     <state>$PROJ_DIR$\..\..\..\iap\modules\settings</state>
                     <state>$PROJ_DIR$\..\..\..\iap\modules\iap</state>
+                    <state>$PROJ_DIR$\..\..\..\iap\modules\io</state>
                     <state>$PROJ_DIR$\..\..\..\iap\user</state>
                     <state>$PROJ_DIR$\..\..\..\libs\thirdparty\freertos\include</state>
                     <state>$PROJ_DIR$\..\..\..\libs\thirdparty\freertos\portable\IAR\ARM_CM4F</state>
@@ -2139,6 +2140,12 @@
                     <name>$PROJ_DIR$\..\..\..\iap\modules\iap\iap.c</name>
                 </file>
             </group>
+            <group>
+                <name>io</name>
+                <file>
+                    <name>$PROJ_DIR$\..\..\..\iap\modules\io\mux.c</name>
+                </file>
+            </group>
             <group>
                 <name>modbus</name>
                 <file>

+ 6 - 0
project/ewarm/iap/iap.ewt

@@ -2379,6 +2379,12 @@
                     <name>$PROJ_DIR$\..\..\..\iap\modules\iap\iap.c</name>
                 </file>
             </group>
+            <group>
+                <name>io</name>
+                <file>
+                    <name>$PROJ_DIR$\..\..\..\iap\modules\io\mux.c</name>
+                </file>
+            </group>
             <group>
                 <name>modbus</name>
                 <file>

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


+ 0 - 1
shared/freemodbus/port/tim_delay.c

@@ -14,7 +14,6 @@ void mb_helper_tim_init(uint32_t baudrate)
     foo = 1.0/((float)baudrate / 11.0);
     foo *= 2000.0; // время в мс (длительность в два символа)
     
-    
     crm_clocks_freq_type crm_clocks_freq_struct = {0};
     
     crm_clocks_freq_get(&crm_clocks_freq_struct);

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