第 2 课 - 输入(按键)控制输出(LED)-中断
今天学习GPIO中断控制LED.一般来说外部中断的使用步骤分为:引脚配置,中断配置,编写中断回调,开启中断。
配置中断引脚
ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
定义回调函数
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
gpio_pin_toggle_dt(&led);
}
定义并初始化gpio_callback
static struct gpio_callback button_cb_data;
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
调用gpio_add_callback()添加回调函数
gpio_add_callback(button.port, &button_cb_data);
删除轮询部分代码
while (1)
{
k_msleep(SLEEP_TIME_MS);
}
完整代码
点击查看代码
/*
* @Author: dengyp sniper15@139.com
* @Date: 2024-11-26 14:18:01
* @LastEditors: dengyp sniper15@139.com
* @LastEditTime: 2025-03-11 09:44:21
* @FilePath: \lesson2_blink\src\main.c
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
*/
/*
* Copyright (c) 2016 Intel Corporation
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>
#define SLEEP_TIME_MS 10000
/* The devicetree node identifier for the "led0" alias. */
#define LED0_NODE DT_ALIAS(led0) //通过别名获取设备树的 led0 节点
// 通过 别名 获取设备树的一个button节点
#define SW0_NODE DT_ALIAS(sw0)
/*
* A build error on this line means your board is unsupported.
* See the sample documentation for information on how to fix this.
*/
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios); //通过节点获取一个 gpio 的实例
// 通过节点获取一个 gpio 的实例
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);
//定义 static struct gpio_callback类型的变量 用于把1个回调函数添加到驱动的回调函数列表中
static struct gpio_callback button_cb_data;
int app_led_init(void)
{
int ret;
//在使用gpio外设之前判断是否可用
if (!gpio_is_ready_dt(&led))
{
return 0;
}
//配置为输出模式
ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE);
if (ret < 0)
{
return 0;
}
return 1;
}
// TODO: 2.定义中断回调函数
void button_pressed(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
gpio_pin_toggle_dt(&led);
}
int app_button_init(void)
{
int ret;
// 判断button 是否可用
if (!gpio_is_ready_dt(&button))
{
return 0;
}
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret < 0) {
return 0;
}
//TODO: 1.配置button 中断 为状态转变为逻辑1时触发
ret = gpio_pin_interrupt_configure_dt(&button, GPIO_INT_EDGE_TO_ACTIVE);
if (ret < 0)
{
return 0;
}
gpio_init_callback(&button_cb_data, button_pressed, BIT(button.pin));
//TODO: 3.添加中断回调函数到button的回调函数列表中
gpio_add_callback(button.port, &button_cb_data);
return 1;
}
int main(void)
{
app_led_init();
app_button_init();
while (1)
{
//TODO: 4.删除轮询代码
k_msleep(SLEEP_TIME_MS);
}
return 0;
}
总结
NCS中外部中断的使用方法跟传统的使用方法没多大区别,不同的地方是中断函数注册,由于zephyr设备驱动的高度解耦,所以回调函数注册稍微麻烦一点。
另外需要注意的一点是,中断的触发方式:上升沿触发(GPIO_INT_EDGE_RISING)和状态变为逻辑1触发(GPIO_INT_EDGE_TO_ACTIVE)是有区别的。

浙公网安备 33010602011771号