3. GPIO中断触发按键事件
任务目标
在 Zephyr OS 中,使用 GPIO 中断 API 为按键注册回调函数,实现按键按下时触发中断并执行事件处理(如翻转 LED 状态),掌握中断驱动开发的基本流程。
环境依赖
- Zephyr OS 3.x(以
nrf52840dk_nrf52840开发板为例) - 板载按键:
DK_BTN1_0(对应 P0.11,低电平有效) - 板载 LED:
DK_LED1(对应 P0.13,高电平点亮)
关键完整代码
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/sys/printk.h>
/* 开发板按键与LED的设备树别名 */
#define SW0_NODE DT_ALIAS(sw0)
#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
static struct gpio_callback button_cb_data;
/* 中断回调函数:翻转LED状态 */
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
gpio_pin_toggle_dt(&led);
printk("Button pressed, LED toggled\n");
}
int main(void)
{
int ret;
/* 配置LED为输出 */
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0) {
return ret;
}
/* 配置按键为输入,并使能内部上拉 */
ret = gpio_pin_configure_dt(&button, GPIO_INPUT | GPIO_PULL_UP);
if (ret < 0) {
return ret;
}
/* 配置按键中断:下降沿触发(按下时电平由高变低) */
ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
if (ret < 0) {
return ret;
}
/* 初始化回调并注册 */
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
gpio_add_callback(button.port, &button_cb_data);
printk("GPIO interrupt example started\n");
while (1) {
k_msleep(1000);
}
return 0;
}
构建与运行
west build -b nrf52840dk_nrf52840 .
west flash
验证方法
- 程序启动后,串口终端应输出
GPIO interrupt example started。 - 按下开发板上的
SW0按键,每次按下时串口输出Button pressed, LED toggled,同时板载 LED1 状态翻转(亮/灭交替)。 - 松开按键后无额外输出,说明中断仅在下降沿触发一次,未发生抖动重复触发(若需消抖可增加软件延时或使用硬件消抖电路)。
关键说明
GPIO_INT_EDGE_TO_ACTIVE表示在按键从非激活电平(高电平)跳变到激活电平(低电平)时触发中断,即按下瞬间触发一次。- 回调函数在中断上下文中执行,应保持简短,避免阻塞操作;本示例仅做 GPIO 翻转和日志输出。
- 若使用其他开发板,需确认设备树中
sw0和led0别名是否存在,或直接使用DT_NODELABEL()引用具体节点。