#include <stdio.h>

#include "esp_log.h"
#include "esp_rom_gpio.h"


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#define GPIO_LED 2
#define GPIO_FAN 15
#define GPIO_KEY 4


// 队列
static QueueHandle_t gpio_evt_queue = NULL;

void gpio_init(void) {
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE; // 禁止中断
    io_conf.mode = GPIO_MODE_OUTPUT; // 通用推挽

    /**
     * 1ULL :表示一个64位无符号整数,,,,     00000000 00000000 00000000 ... 00000001
     * 支持一次配置多个GPIO :
    * .pin_bit_mask = (1ULL << 2) | (1ULL << 4) | (1ULL << 5)
     */
    io_conf.pin_bit_mask = (1ULL << GPIO_LED | 1ULL << GPIO_FAN); // 配置gpio引脚
    io_conf.pull_down_en = 0; // 禁止下拉
    io_conf.pull_up_en = 0; // 禁止上拉


    gpio_config(&io_conf);
}


void gpio_in_init(void) {
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_INPUT; // 输入模式
    io_conf.pin_bit_mask = (1ULL << GPIO_KEY);

    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_ENABLE;

    gpio_config(&io_conf);
}

/**
 * 这个函数是自己写的,,名字随便取
 * @param arg
 * IRAM_ATTR :这个函数放到内部的RAM里面,,, 因为esp32运行代码通常在flash中,,flash擦除,写入,,会很忙,,
 * 如果中断来了,,ISR还在flash,,会崩溃
 */
static void IRAM_ATTR gpio_key_interrupt(void* arg) {

   uint32_t gpio_num =  (uint32_t)arg;
    // NULL : 是否有更高优先级任务被唤醒,,告诉系统,发送数据后,是否应该立即切换任务
    xQueueSendFromISR(gpio_evt_queue, &gpio_num,NULL);
}

static void gpio_task_example(void* pvParameter) {

    uint32_t gpio_num;
    while (1) {
        // 返回pdPASS :成功接收到队列数据
        if (xQueueReceive(gpio_evt_queue, &gpio_num, portMAX_DELAY)) {

            // 消抖时间
            vTaskDelay(pdMS_TO_TICKS(20));

            if (gpio_get_level(gpio_num) == 0) {
                // 按下
                 printf("gpio[%lu] intr,,val is %d  \n",gpio_num,gpio_get_level(gpio_num));
                gpio_set_level(GPIO_LED,0);
                gpio_set_level(GPIO_FAN,0);
            }else {
                gpio_set_level(GPIO_LED,1);
                gpio_set_level(GPIO_FAN,1);
            }


            xQueueReset(gpio_evt_queue);

        }

    }
}


void app_main(void)
{
        // 把引脚从复位功能(UART,SPI,I2C)切回普通GPIO
        // gpio_reset_pin(GPIO_LED);
        //
        // gpio_set_direction(GPIO_LED,GPIO_MODE_OUTPUT);
    gpio_init();

    gpio_set_level(GPIO_LED,1);
    gpio_set_level(GPIO_FAN,1);


    // 输入模式
    // gpio_reset_pin(GPIO_KEY);
    // gpio_set_direction(GPIO_KEY,GPIO_MODE_INPUT);
    // gpio_in_init();


    // 按键中断
    gpio_reset_pin(GPIO_KEY);
    gpio_set_direction(GPIO_KEY, GPIO_MODE_INPUT);
    // 任何一个边沿触发
    gpio_set_intr_type(GPIO_KEY,GPIO_INTR_ANYEDGE);
    // 上拉,,不然浮空,引脚电平会一直变
    gpio_set_pull_mode(GPIO_KEY,GPIO_PULLUP_ONLY);



    // 创建队列
    gpio_evt_queue = xQueueCreate(10,sizeof(uint32_t));

    // 创建一个GPIO中断管理服务,,,让esp-idf有能力管理GPIO中断
    gpio_install_isr_service(0);

    // 注册自己的中断函数
    gpio_isr_handler_add(GPIO_KEY,gpio_key_interrupt,(void*)GPIO_KEY);


    xTaskCreate(gpio_task_example,"gpio_key",2048,NULL,10,NULL);

    while (0) {


        if (gpio_get_level(GPIO_KEY)) {
            // 高电平
            printf("key up \n");
            gpio_set_level(GPIO_LED,1);
            gpio_set_level(GPIO_FAN,1);
        }else {
            printf("key down \n");
            gpio_set_level(GPIO_LED,0);
            gpio_set_level(GPIO_FAN,0);
        }

        vTaskDelay(pdMS_TO_TICKS(100));

        // gpio_set_level(GPIO_LED,0);
        // gpio_set_level(GPIO_FAN,0);
        //
        // // printf("hello world11");
        // vTaskDelay(pdMS_TO_TICKS(1000));
        //

        // gpio_set_level(GPIO_LED,1);
        // gpio_set_level(GPIO_FAN,1);
        // vTaskDelay(pdMS_TO_TICKS(1000));
    }
}


/**
 *
 * 中断不能写printf等输出,,,否则会导致esp32复位,,,  中断处理程序要尽可能的短
 *
 *
 *esp32支持在中断里面直接处理业务逻辑,,但是不建议,,所以会引入队列,信号量,事件组这些机制
 *
 *因为中断环境限制很多,, 比如在按键之后想,,打印信息,控制wifi,发送mqtt,,,这些任务耗时较长
 *
 *中断来了,,,发消息,,让任务去干活
 */
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐