此驱动适用于(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);
}