#include <stdio.h>
#include <inttypes.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#define ESP_INTR_FLAG_DEFAULT 0
#define INPUT_PIN 18
#define LED_PIN 19
// Prototipos de funciones
static void IRAM_ATTR gpio_interrupt_handler(void *args);
void LED_Control_Task(void *params);
uint8_t checkBtn(uint8_t);
// Variables
static QueueHandle_t handlerQueue = NULL;
void app_main()
{
// Configurar LED como salida
gpio_config_t io_conf = {};
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << LED_PIN); // CORREGIDO
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
gpio_config(&io_conf);
// Configurar botón como entrada con interrupción
io_conf.intr_type = GPIO_INTR_POSEDGE;
io_conf.pin_bit_mask = (1ULL << INPUT_PIN); // CORREGIDO
io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_down_en = 1; // Habilitar pull-down
gpio_config(&io_conf);
// Crear la cola de interrupciones
handlerQueue = xQueueCreate(10, sizeof(int));
// Crear la tarea que maneja el LED
xTaskCreate(LED_Control_Task, "LED_Control_Task", 2048, NULL, 1, NULL);
// Instalar ISR y asignar interrupción
gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
gpio_isr_handler_add(INPUT_PIN, gpio_interrupt_handler, (void*) INPUT_PIN);
printf("Minimum free heap size: %"PRIu32" bytes\n", esp_get_minimum_free_heap_size());
// Mantener el programa en ejecución
while (1) {
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
// Manejador de interrupción
static void IRAM_ATTR gpio_interrupt_handler(void *args)
{
int pinNumber = (int) args;
xQueueSendFromISR(handlerQueue, &pinNumber, NULL);
}
// Tarea para controlar el LED
void LED_Control_Task(void *params)
{
int pinNumber, count = 0;
while (true)
{
if (xQueueReceive(handlerQueue, &pinNumber, portMAX_DELAY))
{
if (checkBtn(pinNumber)) {
gpio_set_level(LED_PIN, 1);
printf("GPIO %d was pressed %d times. The state is %d\n", pinNumber, ++count, 1);
while(checkBtn(INPUT_PIN)); // Esperar que se suelte el botón
gpio_set_level(LED_PIN, 0);
printf("GPIO %d was released %d times. The state is %d\n", pinNumber, count, 0);
}
}
}
}
// Función para verificar el estado del botón con debounce
uint8_t checkBtn(uint8_t pinNumber) {
vTaskDelay(50 / portTICK_PERIOD_MS); // Debounce
return gpio_get_level(pinNumber) ? 1 : 0; // Retornar estado del botón
}