[ESP32] 编码旋钮驱动

此驱动适用于(2个引脚ENA,ENB)编码旋钮,当旋钮转动时会产生2个脉冲,若采用定时轮询的方式来获取引脚的电平序列则有可能会丢包。采用中断方式来处理会比较合适;

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"
#include "esp_log.h"

// 定义:旋钮引脚+确认健
#define KNOB_ENA_IO 7
#define KNOB_ENB_IO 8
#define KNOB_KEY_IO 9

static SemaphoreHandle_t g_gpio_sem;

// 顺时针扭动
void turn_clock_wise_proc()
{
    static uint8_t cnt = 0;
    printf("[%ld] CLOCK_WISE.%02X \n", esp_log_timestamp(), cnt++);
}

// 逆时针扭动
void turn_not_clk_wise_proc()
{
    static uint8_t cnt = 0;
    printf("[%ld] N_CLK_WISE.%02X \n", esp_log_timestamp(), cnt++);
}
// 确认键按下
void click_middle_proc()
{
    static uint8_t cnt = 0;
    printf("[%ld] MIDD_BTN.\n", esp_log_timestamp(), cnt++);
}

static void IRAM_ATTR gpio_isr_handler(void *arg)
{
    xSemaphoreGiveFromISR(g_gpio_sem, NULL);
}

static void knob_intr_handle(void *arg)
{
    uint8_t pin_ena = 0;
    uint8_t pin_enb = 0;
    uint8_t knob_value = 0;
    uint8_t knob_value_old = 0;
    uint8_t pin_mid = 0;     // 0:Down,1:Up
    uint8_t pin_mid_old = 1; // Default:Up
    uint8_t last_pos = 0;    // 100:顺时针,200:逆时针

    printf("knob_intr_handle() start,configTICK_RATE_HZ=%d \n", configTICK_RATE_HZ);
    while (1)
    {
        if (xSemaphoreTake(g_gpio_sem, pdMS_TO_TICKS(25))) // raw:portMAX_DELAY
        {
            pin_ena = gpio_get_level(KNOB_ENA_IO);
            pin_enb = gpio_get_level(KNOB_ENB_IO);
            knob_value = pin_ena << 1 | pin_enb;
            // printf("info=> %d,%d; old=%d, curr=%d \n", pin_ena,pin_enb,knob_value_old,knob_value);
            if (knob_value == 2 && knob_value_old == 1)
            {
                last_pos = 100;
            }
            else if (knob_value == 3 && knob_value_old == 0)
            {
                last_pos = 200;
            }
            knob_value_old = knob_value;
            if (knob_value == 2 || knob_value == 1)
            {
               //if(last_pos==100)//防止误触
                turn_clock_wise_proc();
            }
            else if (knob_value == 3 || knob_value == 0)
            {
               //if(last_pos==200)//防止误触
                turn_not_clk_wise_proc();
            }
        }
        pin_mid = gpio_get_level(KNOB_KEY_IO);
        if (pin_mid_old != pin_mid)
        {
            pin_mid_old = pin_mid;
            if (pin_mid == 0)
                click_middle_proc();
        }
    }
}

/*Init Knob & key*/
void Knob_key_Init(void)
{
    gpio_config_t io_cfg = {
        .intr_type = GPIO_INTR_DISABLE,
        .mode = GPIO_MODE_INPUT,
        .pin_bit_mask = BIT64(KNOB_ENA_IO) | BIT64(KNOB_ENB_IO) | BIT64(KNOB_KEY_IO),
    };
    gpio_config(&io_cfg);

    // install gpio isr service
    gpio_install_isr_service(0); // 0=ESP_INTR_FLAG_DEFAULT

    // zero-initialize the config structure.
    gpio_config_t io_conf = {};

    // interrupt of rising edge
    //  GPIO_INTR_ANYEDGE;//GPIO_INTR_POSEDGE;//GPIO_INTR_NEGEDGE
    io_conf.intr_type = GPIO_INTR_ANYEDGE; // GPIO_INTR_POSEDGE;//GPIO_INTR_NEGEDGE
    io_conf.pin_bit_mask = 1ULL << KNOB_ENA_IO;
    io_conf.mode = GPIO_MODE_INPUT;
    io_conf.pull_up_en = 1;
    gpio_config(&io_conf);

    g_gpio_sem = xSemaphoreCreateBinary();
    // start gpio task
    xTaskCreate(knob_intr_handle, "knob_intr_handle", 1024 * 5, NULL, 10, NULL);
    gpio_isr_handler_add(KNOB_ENA_IO, gpio_isr_handler, NULL);
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值