2. GPIO输出控制LED闪烁

任务目标

在Zephyr RTOS环境下,通过设备树声明LED引脚,利用GPIO API实现LED周期性闪烁(亮100ms、灭100ms),以此掌握设备树节点配置与gpio_pin_configure/gpio_pin_toggle等核心API的调用方法。

硬件与工程配置

以nRF52840DK开发板为例(其他开发板需按实际原理图调整设备树)。板载LED0对应P0.13引脚,低电平点亮。工程文件结构如下:


app/
├── CMakeLists.txt
├── prj.conf
└── src/
    └── main.c

CMakeLists.txt(最小工程定义):


cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(blinky)
target_sources(app PRIVATE src/main.c)

prj.conf:本案例无需额外配置项,文件可为空或仅包含注释。

设备树LED节点

Zephyr默认设备树已包含led0节点(位于zephyr/boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840-common.dtsi),其定义如下:


leds {
    compatible = "gpio-leds";
    led0: led_0 {
        gpios = <&gpio0 13 GPIO_ACTIVE_LOW>;
        label = "Green LED 0";
    };
};

若使用自定义开发板,需在板级设备树中补充上述节点,并确保gpio0节点状态为okay。

关键完整代码

src/main.c:


#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/devicetree.h>

/* 从设备树获取LED0节点及其GPIO配置 */
#define LED0_NODE DT_ALIAS(led0)

#if !DT_NODE_HAS_STATUS(LED0_NODE, okay)
#error "Device tree node 'led0' not found or not okay"
#endif

static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

#define SLEEP_TIME_MS   100

int main(void)
{
    int ret;

    /* 校验GPIO控制器是否就绪 */
    if (!gpio_is_ready_dt(&led)) {
        return -1;
    }

    /* 配置LED引脚为输出模式,初始电平由设备树极性决定(此处为低电平点亮,初始为灭) */
    ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_INACTIVE);
    if (ret < 0) {
        return ret;
    }

    while (1) {
        /* 翻转引脚电平 */
        ret = gpio_pin_toggle_dt(&led);
        if (ret < 0) {
            return ret;
        }
        k_msleep(SLEEP_TIME_MS);
    }
    return 0;
}

构建与运行


# 在app目录下执行
west build -b nrf52840dk_nrf52840 .
west flash

验证方法

烧录后观察开发板LED0:应呈现周期为200ms的闪烁(亮100ms、灭100ms)。若LED状态相反(常亮或常灭),检查GPIO_ACTIVE_LOW极性是否与硬件原理图匹配;若LED不亮,使用west build -t menuconfig确认CONFIG_GPIO已启用(默认开启),并检查设备树中led0别名是否存在。

常见问题

  • 编译报错“led0 not found”:确认板级设备树包含led0节点,且chosen节点中定义了zephyr,console等必要别名(部分板卡需手动添加aliases { led0 = &led0; };)。
  • 引脚无输出:检查GPIO控制器在设备树中是否使能(status = "okay"),并确认引脚号与原理图一致。