单片机学习小组
直播中

h1654155272.9717

8年用户 1259经验值
擅长:电源/新能源
私信 关注

按键检测gpio中断的方式方法有哪几种?

按键检测gpio中断的方式方法有哪几种?

回帖(1)

刘飞云

2022-2-7 11:52:07
前言
最近在做一个按键检测,按键检测有两种方法,一种是轮询法,即在rtos中建立一个任务,然后在死循环中判断按键状态,还有一种方式是使用中断,注册一个事件,事件触发后,会向RTOS队列写入数据。
在官方示例examplesperipheralsgpio中有相关代码


流程
选定gpio
首先选定gpio,由于我使用4个按键,故需要四个gpio


#define INPUT_UP     34
#define INPUT_LEFT   35
#define INPUT_RIGHT  32
#define INPUT_DOWN    33


#define GPIO_INPUT_PIN_SEL  ((1ULL< #define ESP_INTR_FLAG_DEFAULT 0//设置一个flag标志位
static xQueueHandle gpio_evt_queue = NULL;//消息队列


gpio配置
首先初始化gpio结构体 gpio_config_t io_conf;
然后配置触发类型 io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
一共有一下类型


typedef enum {
    GPIO_PIN_INTR_DISABLE = 0,//不使能
    GPIO_PIN_INTR_POSEDGE = 1,//上升沿
    GPIO_PIN_INTR_NEGEDGE = 2,//下降沿
    GPIO_PIN_INTR_ANYEDGE = 3,//任何变化
    GPIO_PIN_INTR_LOLEVEL = 4,//低电平触发
    GPIO_PIN_INTR_HILEVEL = 5//高电平触发
} GPIO_INT_TYPE;


由于我将按键一端接在3.3v,所以这里选择下降沿触发。
然后选择io口


io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;


然后设置模式,由于是下降沿触发,故平常应该io口上拉,使能并配置


io_conf.mode = GPIO_MODE_INPUT;
io_conf.pull_up_en = 1;
gpio_config(&io_conf);


设置回调函数
首先初始化队列,然后创建一个接受函数


gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    start gpio task
xTaskCreate(anjian, "get down", 2048, NULL, 10, NULL);


在接受函数中读取队列信息


static void anjian(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%d] intr, val: %dn", io_num, gpio_get_level(io_num));
        }
    }
}


注册中断处理程序
注册中断函数,并将按键触发加入中断函数


   gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(INPUT_UP, gpio_isr_handler, (void*) INPUT_UP);
    gpio_isr_handler_add(INPUT_DOWN, gpio_isr_handler, (void*) INPUT_DOWN);
    gpio_isr_handler_add(INPUT_LEFT, gpio_isr_handler, (void*) INPUT_LEFT);
    gpio_isr_handler_add(INPUT_RIGHT, gpio_isr_handler, (void*) INPUT_RIGHT);


按键触发后将进入gpio_isr_handler回调函数中,然后在中断函数中将按键标号写入队列。


static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}


然后就是在之前的按键函数中从队列中读取按键信息
举报

更多回帖

发帖
×
20
完善资料,
赚取积分