在本练习中,我们将修改 blinky 示例,使得 LED1 仅在按下按钮 1 时点亮,如下图所示。B
在 nRF54 DK 上,开发板的 LED 和按钮标有以 0 开头的 PCB 标签(PCB 丝印)(LED0-LED3 和 BUTTON0-BUTTON3)。在上一代开发套件中,索引从 1 开始(LED1-LED4)。因此,在 nRF54L15 DK 上,我们将使用 LED0 和 BUTTON0。
为此,我们将使用 GPIO 通用 API 中讨论的轮询方法。这是通过不断轮询 CPU 以检查按钮是否被按下,然后相应地更新 LED 来实现的。在接下来的练习 2 中,我们将学习如何使用 GPIO 中断,这比轮询更省电。
如果我们回顾 nRF52833 DK 的原理图,有四个按钮连接到与 LED 相同的 GPIO 外设 GPIO0(节点标签:gpio0)。这可以在 GPIO 引脚映射中看到,例如,请注意按钮 1 连接到 P0.11。P0 中的 0 象征着它是 &gpio0。
这就是为什么 LED 和按钮都需要相同的驱动程序。这从 DK 的设备树文件 nrf52833dk_nrf52833.dts 中也可以明显看出。
buttons {
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 0";
};
button1: button_1 {
gpios = <&gpio0 12 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 1";
};
/* ... */
};
};
/* ... */
/* These aliases are provided for compatibility with samples */
aliases {
/* ... */
sw0 = &button0;
sw1 = &button1;
sw2 = &button2;
sw3 = &button3;
bootloader-led0 = &led0;
};
};DevicetreenRF52833 DK 上的按钮 1 被赋予节点名称 button_0,它具有别名 (sw0) 和节点标签 (button0),并连接到 &gpio0、pin 11。请记住,设备树文件中的索引始终从 0 开始,这就是为什么开发板上的按钮 1 被称为 button0。
gpios = <&gpio0 11 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;Devicetree如果按钮连接到与 LED 不同的 GPIO 端口(例如 gpio1),则需要一个新的设备指针。例如,nRF54L15 DK 的 LED 位于 gpio1 和 gpio2 上,而按钮连接到 gpio0 和 gpio1。
1. 克隆 nRF Connect SDK Fundamentals GitHub 仓库。请注意,该仓库包含练习代码库和解决方案。请务必选择与您选择的 nRF Connect SDK 版本相对应的分支:

main (默认分支):适用于 nRF Connect SDK v3.2.0 版本这里我们有两个选择。我们可以使用 VS Code 中的图形用户界面(在步骤 1.1 中描述)或命令行(在步骤 1.2 中描述)来克隆 GitHub 仓库。选择 1.1 或 1.2 即可。
1.1 复制仓库链接并使用 VS Code 的命令面板(Command Palette)克隆仓库。
转到“查看” -> “命令面板” -> 输入 Git Clone 并粘贴仓库链接。将仓库保存在靠近根目录的位置。
1.2 或者,在靠近根目录的地方创建一个文件夹,并通过在 nRF Connect 终端中运行以下命令来克隆仓库(在 VS Code 中,通过查看 → 终端(或 Ctrl+J)打开终端,然后单击启动配置文件…下拉菜单(+ 旁边的箭头)并选择 nRF Connect)。
git clone https://github.com/NordicDeveloperAcademy/ncs-fund.gitBash发出命令后,课程代码库将被克隆到当前工作目录中。
确保仓库路径中没有空格或其他特殊字符。
2. 在 VS Code 中打开本练习的练习代码库。
2.1 在 nRF Connect 扩展的欢迎视图中,单击打开现有应用程序。

选择本练习的基础代码(位于您所使用的版本的 l2/l2_e1 中),然后单击选择文件夹。
2.2 从 VS Code 的资源管理器中打开 main.c,如下面的屏幕截图所示:

3. 在硬件上初始化按钮。
3.1 通过别名 sw0 获取按钮 1 的节点标识符。
回想一下设备树章节,DK 设备树中的 /aliases 节点为节点 &button0 定义了别名 sw0。下面这行代码使用宏调用 DT_ALIAS() 通过别名访问该节点的节点标识符。
在 main.c 中,搜索 STEP 3.1 并添加(复制并粘贴)以下行:
#define SW0_NODE DT_ALIAS(sw0) C这样做是为了确保跨不同硬件的兼容性。
3.2 通过 gpio_dt_spec 获取设备指针、引脚号和引脚配置标志。
GPIO API 有一个名为 gpio_dt_spec 的结构体,它封装了所有这些信息,并且可以使用 GPIO_DT_SPEC_GET() 来检索。
在 main.c 中,搜索 STEP 3.2 并添加(复制并粘贴)以下行:
static const struct gpio_dt_spec button = GPIO_DT_SPEC_GET(SW0_NODE, gpios);C这行代码使用宏 GPIO_DT_SPEC_GET() 来填充 gpio_dt_spec 变量的成员:
const struct device *portgpio_pin_t pingpio_dt_flags_t dt_flags4. 在使用设备之前,通过调用 device_is_ready() 来验证设备是否已准备就绪,这一点非常重要。

device_is_ready()在 main.c 中,搜索 STEP 4 并添加(复制并粘贴)以下行:
if (!device_is_ready(button.port)) {
return -1;
}C5. 将连接到按钮的引脚配置为输入引脚,并设置其硬件规格。
在 main() 内部,搜索 STEP 5 并添加以下行:
ret = gpio_pin_configure_dt(&button, GPIO_INPUT);
if (ret < 0) {
return -1;
}C6. 在本练习的主循环中,我们将无限期地轮询 CPU 以读取按钮的状态(按下 = 1,未按下 = 0),并根据按钮的状态更新 LED。
6.1 读取按钮的状态并将其存储。
使用 gpio_pin_get_dt() 读取 button.pin 的当前状态,并将其保存在变量 val 中。
搜索 STEP 6.1 并在无限循环内添加以下代码:
bool val = gpio_pin_get_dt(&button);C6.2 根据按钮状态更新 LED
使用 gpio_pin_set_dt() 更新 LED,以反映上一步中保存在变量 val 中的按钮当前状态。
搜索 STEP 6.2 并在无限循环内添加以下代码:
gpio_pin_set_dt(&led,val);C7. 将休眠时间从 1000 ms 更改为 100 ms。100 ms 是让主线程休眠并仍能在按下按钮时及时响应的合适时间。
8. 添加构建配置,就像我们在第 1 课练习 2 中所做的那样。
9. 构建练习并将其烧录到开发板上,就像我们在上一课中所做的那样。观察当按下按钮 1 时,LED1 点亮。(请记住,在 nRF54L15 DK 上,那将是 button0 和 LED0)
本练习的解决方案可以在 GitHub 仓库中找到,位于您所使用的版本的 l2/l2_e1_sol 中。