跳到主要内容

GPIO 与中断教程

TKL GPIO 接口用于将引脚配置为数字输入、输出或中断驱动的事件处理。你设置引脚的模式与方向,读写其电平,并可选地为边沿或电平事件挂载中断回调。

先决条件

  • 已完成 环境搭建
  • 开发板在 Kconfig 中设置了 ENABLE_GPIO=y

数字输出(LED 闪烁)

#include "tkl_gpio.h"
#include "tal_system.h"

#define LED_PIN TUYA_GPIO_NUM_18

void blink_led(void)
{
TUYA_GPIO_BASE_CFG_T cfg = {
.mode = TUYA_GPIO_PUSH_PULL,
.direct = TUYA_GPIO_OUTPUT,
.level = TUYA_GPIO_LEVEL_LOW,
};
tkl_gpio_init(LED_PIN, &cfg);

while (1) {
tkl_gpio_write(LED_PIN, TUYA_GPIO_LEVEL_HIGH);
tal_system_sleep(500);
tkl_gpio_write(LED_PIN, TUYA_GPIO_LEVEL_LOW);
tal_system_sleep(500);
}
}

数字输入(读取按键)

#define BUTTON_PIN TUYA_GPIO_NUM_0

void read_button(void)
{
TUYA_GPIO_BASE_CFG_T cfg = {
.mode = TUYA_GPIO_PULLUP,
.direct = TUYA_GPIO_INPUT,
};
tkl_gpio_init(BUTTON_PIN, &cfg);

TUYA_GPIO_LEVEL_E level;
tkl_gpio_read(BUTTON_PIN, &level);

if (level == TUYA_GPIO_LEVEL_LOW) {
TAL_PR_INFO("button pressed");
}
}

中断驱动输入

要获得灵敏的按键响应,使用 GPIO 中断而非轮询:

static void button_isr(void *arg)
{
/* ISR 上下文 -- 保持简短 */
/* 通过信号量或队列投递到线程中处理 */
}

void setup_interrupt(void)
{
TUYA_GPIO_IRQ_T irq_cfg = {
.mode = TUYA_GPIO_IRQ_FALL,
.cb = button_isr,
.arg = NULL,
};
tkl_gpio_irq_init(BUTTON_PIN, &irq_cfg);
tkl_gpio_irq_enable(BUTTON_PIN);
}

中断模式

模式触发方式
TUYA_GPIO_IRQ_RISE上升沿(LOW -> HIGH)
TUYA_GPIO_IRQ_FALL下降沿(HIGH -> LOW)
TUYA_GPIO_IRQ_RISE_FALL双边沿
TUYA_GPIO_IRQ_LOW低电平
TUYA_GPIO_IRQ_HIGH高电平

中断配合软件消抖

机械按键会产生抖动。结合中断和定时器实现干净的检测:

static TIMER_ID s_debounce_timer;

static void debounce_cb(TIMER_ID id, void *arg)
{
TUYA_GPIO_LEVEL_E level;
tkl_gpio_read(BUTTON_PIN, &level);
if (level == TUYA_GPIO_LEVEL_LOW) {
TAL_PR_INFO("confirmed press");
}
}

static void button_isr(void *arg)
{
tkl_gpio_irq_disable(BUTTON_PIN);
tal_sw_timer_start(s_debounce_timer, 50, TAL_TIMER_ONCE);
}

:::tip TDL 按键框架 对于产品级按键处理(长按、连按、多按键支持),使用 TDL 按键框架 而非原始 GPIO 中断。TDL 已处理消抖、边沿检测与事件回调。 :::

GPIO 上下拉模式

模式常量用途
推挽输出TUYA_GPIO_PUSH_PULLLED、继电器、使能脚
上拉输入TUYA_GPIO_PULLUP低电平有效按键
下拉输入TUYA_GPIO_PULLDOWN高电平有效传感器
开漏TUYA_GPIO_OPENDRAINI2C bit-bang、共享总线
开漏 + 上拉TUYA_GPIO_OPENDRAIN_PULLUP带内部上拉的 I2C
浮空TUYA_GPIO_FLOATING外部上拉电阻

清理

tkl_gpio_irq_disable(BUTTON_PIN);
tkl_gpio_deinit(BUTTON_PIN);

tkl_gpio_deinit() 会移除 ISR 处理函数、关闭中断并复位引脚。

平台说明

  • ESP32 经典款: GPIO 34-39 仅输入,输出模式将失败。
  • ESP32-S3: GPIO 22-25 为 NC,不要使用。
  • ESP32-C3: 仅 22 个 GPIO(0-21)。
  • 所有平台: ISR 服务在首次调用 tkl_gpio_irq_init() 时全局安装,并由所有引脚共享。

参考资料