Загрузка данных


Схема подключения (Пины для ESP32-WROOM-32)
Для матричной клавиатуры 4x4 требуется 8 пинов: 4 выхода для строк (Row) и 4 входа для столбцов (Column). [1]
Важно для ESP32: Избегайте пинов с ограничением по режиму (например, GPIO 34–39 работают только на вход и без подтяжки), а также пинов, влияющих на загрузку (0, 2, 5, 12, 15). [1, 2]
Пример безопасных пинов:
•	Строки (Row 1–4): GPIO 16, 17, 18, 19 (настроить как выходы GPIO_MODE_OUTPUT)
•	Столбцы (Column 1–4): GPIO 21, 22, 23, 25 (настроить как входы с подтяжкой к питанию GPIO_MODE_INPUT + включить GPIO_PULLUP_ENABLE)
   
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"

static const char *TAG = "KEYPAD";

// Определение пинов строк и столбцов
#define ROW_COUNT 4
#define COL_COUNT 4

static const gpio_num_t row_pins[ROW_COUNT] = { GPIO_NUM_16, GPIO_NUM_17, GPIO_NUM_18, GPIO_NUM_19 };
static const gpio_num_t col_pins[COL_COUNT] = { GPIO_NUM_21, GPIO_NUM_22, GPIO_NUM_23, GPIO_NUM_25 };

// Раскладка клавиатуры 4x4
static const char key_map[ROW_COUNT][COL_COUNT] = {
    { '1', '2', '3', 'A' },
    { '4', '5', '6', 'B' },
    { '7', '8', '9', 'C' },
    { '*', '0', '#', 'D' }
};

void keypad_init(void) {
    // Настраиваем строки как выходы
    for (int i = 0; i < ROW_COUNT; i++) {
        gpio_config_t io_conf = {
            .pin_bit_mask = (1ULL << row_pins[i]),
            .mode = GPIO_MODE_OUTPUT,
            .pull_up_en = GPIO_PULLDOWN_DISABLE,
            .pull_down_en = GPIO_PULLDOWN_DISABLE,
            .intr_type = GPIO_INTR_DISABLE,
        };
        gpio_config(&io_conf);
        gpio_set_level(row_pins[i], 1); // Изначально высокий уровень
    }

    // Настраиваем столбцы как входы с подтяжкой вверх
    for (int j = 0; j < COL_COUNT; j++) {
        gpio_config_t io_conf = {
            .pin_bit_mask = (1ULL << col_pins[j]),
            .mode = GPIO_MODE_INPUT,
            .pull_up_en = GPIO_PULLUP_ENABLE,
            .pull_down_en = GPIO_PULLDOWN_DISABLE,
            .intr_type = GPIO_INTR_DISABLE,
        };
        gpio_config(&io_conf);
    }
}

char keypad_scan(void) {
    char pressed_key = '\0';

    for (int r = 0; r < ROW_COUNT; r++) {
        // Устанавливаем текущую строку в LOW (0)
        gpio_set_level(row_pins[r], 0);

        for (int c = 0; c < COL_COUNT; c++) {
            // Если на столбце LOW — кнопка нажата
            if (gpio_get_level(col_pins[c]) == 0) {
                pressed_key = key_map[r][c];
                // Ждем отпускания клавиши (простейший антидребезг)
                vTaskDelay(pdMS_TO_TICKS(50));
                while (gpio_get_level(col_pins[c]) == 0) {
                    vTaskDelay(pdMS_TO_TICKS(10));
                }
                break;
            }
        }

        // Возвращаем строку в HIGH (1)
        gpio_set_level(row_pins[r], 1);
        if (pressed_key != '\0') {
            break;
        }
    }

    return pressed_key;
}

void keypad_task(void *pvParameters) {
    keypad_init();
    char last_key = '\0';

    while (1) {
        char key = keypad_scan();
        if (key != '\0') {
            ESP_LOGI(TAG, "Pressed key: %c", key);
        }
        vTaskDelay(pdMS_TO_TICKS(50));
    }
}

void app_main(void) {
    xTaskCreate(keypad_task, "keypad_task", 2048, NULL, 5, NULL);
}