Zephyr下控制ESP32S3的GPIO口

1.关于esp32s3脚的定义

下面以GPIO38为例介绍esp32s3下GPIO口的控制,参考ESP32S3-wroom-1规格书,关于GPIO38接口的定义如下:


由上表可知GPIO38与SPI复用引脚

2.查看esp32s3_devkitm对应的设备树定义

这里我选用的是esp32s3_devkitm/esp32s3/procpu,因此我查找关于这个board的dts定义,如下所示

进入文件,查看关于GPIO38和SPI的定义,没有关于GPIO38的定义,SPI的定义如下,对应的SPI功能默认全部打开,需要将其禁用,让gpio功能开启:

继续查找关于GPIO的定义

关于"esp32s3_mini_n8.dtsi"里面定义了Flash和RAM的大小

关于"esp32s3_devkitm-pinctrl.dtsi",里面定义各个功能对应的PIN脚;

GPIO38用于SPI3的CS脚。

3.控制GPIO38对应的设备树

需要进一步获取系统关于GPIO的定义,由上可知,esp32s3_devkitm更底层,引用了esp32s3_common.dtsi,进一步查看:

gpio0寄存器控制GPIO0-31这32个GPIO;

gpio1寄存器控制GPIO32-53这22个GPIO;

因此,选用gpio1寄存器,具体设备树定义,如下所示:

复制代码
#include <zephyr/dt-bindings/gpio/gpio.h>

/ {
    aliases {
        led0 = &user_led; // 别名正确指向LED节点
    };
    leds {
        compatible = "gpio-leds";
        user_led: led_0 {
            gpios = <&gpio1 38 GPIO_ACTIVE_LOW>;
            status = "okay";
        };
    };
};

&spi3 {
	status = "disabled"; //禁用spi3,释放对应io脚
};

&gpio1 {
    status = "okay"; // gpio1控制器必须启用
};

4.控制GPIO38

下面控制GPIO38,使其对应的LED灯亮1s,灭1s,如下所示

复制代码
#include <zephyr/kernel.h>
#include <zephyr/drivers/gpio.h>

#define LED0_NODE DT_ALIAS(led0)
static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(LED0_NODE, gpios);

int main(void)
{
    int ret;
    bool current_state;

    if (!gpio_is_ready_dt(&led)) {
        printk("LED GPIO not ready\n");
        return 0;
    }
    
    // 配置为输出,初始高电平(灭,因GPIO_ACTIVE_LOW)
    ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT | GPIO_PUSH_PULL);
    if (ret != 0) {
        printk("Configure failed: %d\n", ret);
        return 0;
    }
    
    while (1) {
        ret = gpio_pin_set_dt(&led, 1); // 1对应高电平(因ACTIVE_LOW,此时LED应灭)
        if (ret != 0) {
            printk("Set high failed: %d\n", ret);
        }
        int level = gpio_pin_get_dt(&led);
        printk("After set high, level = %d\n", level); // 预期应为1
        k_msleep(1000);

        printk("Testing set low...\n");
        ret = gpio_pin_set_dt(&led, 0); // 0对应低电平(LED应亮)
        if (ret != 0) {
            printk("Set low failed: %d\n", ret);
        }
        level = gpio_pin_get_dt(&led);
        printk("After set low, level = %d\n", level); // 预期应为0
        k_msleep(1000);
    }
    return 0;
}

ESP32-S3 的部分 GPIO(尤其是 34~39 号引脚)默认配置为输入专用模式(无内部上拉 / 下拉电阻)。如果你的 LED 连接在这类引脚上,即使配置为输出,读取电平(输入操作)时可能无法正确获取输出状态,导致gpio_pin_get_dt始终返回 0。

5.控制 GP IO0做按键



代码如下:

复制代码
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>

#define KEY_NODE DT_ALIAS(sw0)
static const struct gpio_dt_spec key = GPIO_DT_SPEC_GET (KEY_NODE, gpios);

static int64_t last_mode_change;
volatile uint8_t pwm_mode = 1;

static void change_mode(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
{
        (void) dev;
        (void) cb;
        (void) pins;

        int64_t now = k_uptime_get();

        if (now - last_mode_change > 300) {
		pwm_mode = (pwm_mode)?0:1;
                last_mode_change = now;
        }
}

int main(void)
{
	struct gpio_callback button_cb_data;
	int ret;

	if(!gpio_is_ready_dt(&key)) {
		printf("Error: GPIO device not ready!\n");
		return -1;
	}
	ret = gpio_pin_configure_dt(&key, GPIO_INPUT);
	if(ret != 0) {
		printf("Failed to configure.key (ret = %d)\n", ret);
		return -1;
	}
	gpio_pin_interrupt_configure_dt(&key, GPIO_INT_EDGE_RISING);
	gpio_init_callback(&button_cb_data, change_mode, BIT(key.pin));
	gpio_add_callback(key.port, &button_cb_data);

	while(1) {
		printk("pwm_mode = %d\n", pwm_mode);
	}
	return 0;
}

运行后,执行结果如下:

相关推荐
ElfBoard22 分钟前
飞凌精灵(ElfBoard)技术贴|如何在RK3506开发板上实现UART功能复用
大数据·linux·人工智能·驱动开发·单片机·嵌入式硬件·物联网
HackTorjan30 分钟前
AI驱动的制品库高效管理:智能分类、自动化追踪与全生命周期优化
linux·人工智能·分类·自动化
.千余36 分钟前
【Linux】进程概念
linux·服务器·开发语言·学习
蜡台39 分钟前
centos 8 安装 nginx-1.29.8 及相关配置教程
linux·nginx·centos
爱学习的小囧39 分钟前
ESXi性能历史怎么监控?2种方法,图形化+命令行全覆盖
java·linux·运维·服务器·网络·esxi·esxi8.0
踏着七彩祥云的小丑1 小时前
嵌入式——认识电子元器件——二极管系列
单片机·嵌入式硬件
Jack_02201 小时前
基于51单片机的智能电动窗帘控制OLED显示设计
单片机·嵌入式硬件·51单片机·智能家居·oled显示·电动窗帘
sz4972385991 小时前
vscode多种编译环境共存的方法
ide·vscode·stm32·编辑器·esp32
sagima_sdu1 小时前
Codex 使用指南(技术向):App、CLI 与工作流接入
linux·运维·语言模型·json
圆山猫1 小时前
[Linux] 用 Buildroot 为 RISC-V QEMU 构建最小根文件系统
linux·运维·risc-v