长按短按控制LED灯-ESP32中断处理
#include <stdio.h> #include <string.h> #include <stdlib.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/queue.h" #include "driver/gpio.h" #include <sys/time.h> typedef enum { KEY_SHORT_PRESS = 1, KEY_LONG_PRESS =2, } alink_key_t; #define GPIO_LED_IO 13 #define GPIO_LED_PIN_SEL 1ULL<<GPIO_LED_IO #define GPIO_KEY_IO 14 #define GPIO_KEY_PIN_SEL 1ULL<<GPIO_KEY_IO static xQueueHandle gpio_evt_queue = NULL; //获取系统时间 static int64_t get_time(){ struct timeval tv_now; gettimeofday(&tv_now, NULL); int64_t time_us = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec; return time_us; } //按键中断处理函数 static void IRAM_ATTR gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t) arg; xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); } //任务处理 static void led_task(void* arg) { uint32_t io_num; BaseType_t press_key = pdFALSE; BaseType_t lift_key = pdFALSE; int backup_time = 0; for(;;) { if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) { printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num)); //记录下用户按下按键的时间点 if (gpio_get_level(io_num) == 0) { press_key = pdTRUE; backup_time = get_time(); //如果当前GPIO口的电平已经记录为按下,则开始减去上次按下按键的时间点 } else if (press_key) { //记录抬升时间点 lift_key = pdTRUE; backup_time = get_time() - backup_time; } //按下标志位和按键弹起标志位都为1时候 if (press_key & lift_key) { press_key = pdFALSE; lift_key = pdFALSE; //大于1秒为长按 if (backup_time > 1000000) { printf("长按 ... \r\n"); //关闭LED灯 gpio_set_level(GPIO_LED_IO, 0); } else { printf("短按 ... \r\n"); //打开LED灯 gpio_set_level(GPIO_LED_IO, 1); } } } } } void app_main(void) { //LED引脚配置 gpio_config_t io_conf; io_conf.intr_type = GPIO_INTR_DISABLE; io_conf.mode = GPIO_MODE_OUTPUT; io_conf.pin_bit_mask = GPIO_LED_PIN_SEL; io_conf.pull_down_en = 0; io_conf.pull_up_en = 0; gpio_config(&io_conf); //按键中断配置 io_conf.intr_type = GPIO_INTR_ANYEDGE; io_conf.pin_bit_mask = GPIO_KEY_PIN_SEL; io_conf.mode = GPIO_MODE_INPUT; io_conf.pull_up_en = 1; gpio_config(&io_conf); //创建消息队列处理引脚中断事件 gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t)); //创建任务 xTaskCreate(led_task, "led_task", 2048, NULL, 10, NULL); //第一个处理器核安装中断处理程序 gpio_install_isr_service(0); //添加中断处理函数 gpio_isr_handler_add(GPIO_KEY_IO, gpio_isr_handler, (void*) GPIO_KEY_IO); printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size()); }
参考:https://gitee.com/EspressifSystems/esp-idf