首页 > 其他分享 >ESP32-IDF GPIO 专题

ESP32-IDF GPIO 专题

时间:2024-10-17 08:52:16浏览次数:10  
标签:ESP isr ESP32 引脚 num gpio IDF GPIO

目录


一、基本介绍

API 参考路径 esp-idf/components/esp_driver_gpio/include/driver/gpio.h

ESP-IDF 由多个组件组成,组件中包含专门为 ESP 芯片编写的代码或第三方库(即第三方组件)。对于某些第三方库,ESP-IDF 提供专用的包装器和接口,以简化对第三方库的使用,或提高其与 ESP-IDF 其他功能的兼容性。某些情况下,第三方组件将直接呈现底层库的原始 API。

1、配置结构体

为确保应用程序与未来 ESP-IDF 版本的兼容性,请正确初始化配置结构体。

多数 ESP-IDF 中的初始化、配置和安装函数(通常以 ..._init()..._config()..._install() 命名)都需要一个指向配置结构体的指针作为参数。例如:

const esp_timer_create_args_t my_timer_args = {
    .callback = &my_timer_callback,
    .arg = callback_arg,
    .name = "my_timer"
};
esp_timer_handle_t my_timer;
esp_err_t err = esp_timer_create(&my_timer_args, &my_timer);

初始化函数不会存储指向配置结构体的指针,因此在栈上分配结构体是安全的。

下面介绍 GPIO 的配置结构体:

typedef struct {
    uint64_t pin_bit_mask;          /*!< GPIO pin: set with bit mask, each bit maps to a GPIO */
    gpio_mode_t mode;               /*!< GPIO mode: set input/output mode                     */
    gpio_pullup_t pull_up_en;       /*!< GPIO pull-up                                         */
    gpio_pulldown_t pull_down_en;   /*!< GPIO pull-down                                       */
    gpio_int_type_t intr_type;      /*!< GPIO interrupt type                                  */
#if SOC_GPIO_SUPPORT_PIN_HYS_FILTER
    gpio_hys_ctrl_mode_t hys_ctrl_mode;       /*!< GPIO hysteresis: hysteresis filter on slope input    */
#endif
} gpio_config_t;
  • pin_bit_mask:GPIO 引脚号。
    • 比如 GPIO_NUM_2,则配置为 .pin_bit_mask = (1 << GPIO_NUM_2)
  • mode:选择输入/输出模式
  • pull_up_en:引脚上拉设置
  • pull_down_en:引脚下拉设置
  • intr_type:中断模式

有关这几个类型的定义在本文第三小节可以找到

2、API

在使用 GPIO 相关的 API 时,要加上头文件:

#include "driver/gpio.h"

2.1 gpio_config

esp_err_t gpio_config(const gpio_config_t *pGPIOConfig);
  • 参数
    • pGPIOConfig:GPIO 配置结构体,见第一小节
  • 作用:
    • 该函数用于初始化 GPIO 的 Mode、pull-up、PullDown、IntrType,
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.2 gpio_reset_pin

esp_err_t gpio_reset_pin(gpio_num_t gpio_num)
  • 参数:
    • gpio_num:引脚号
  • 作用
    • 重置 GPIO 到默认状态(选择 GPIO 功能,启用上拉,禁用输入和输出)。
  • 返回值
    • 总是返回 ESP_OK

2.3 gpio_set_intr_type

esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type)
  • 参数
    • gpio_num:引脚号
    • intr_type:中断类型,见第三小节
  • 作用
    • 设置 GPIO 中断类型
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.4 gpio_intr_enable

esp_err_t gpio_intr_enable(gpio_num_t gpio_num)
  • 参数
    • gpio_num:引脚号
  • 作用
    • 使能 GPIO 中断
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.5 gpio_intr_disable

esp_err_t gpio_intr_disable(gpio_num_t gpio_num)
  • 参数
    • gpio_num:引脚号
  • 作用
    • 禁用 GPIO 中断
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.6 gpio_set_level

esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level)
  • 参数
    • gpio_num:引脚号
    • level:0: 低;1: 高
  • 作用
    • 设置 GPIO 输出电平
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

通过启用 CONFIG_GPIO_CTRL_FUNC_IN_IRAM,此函数允许在 ISR 上下文中禁用缓存的情况下执行。

2.7 gpio_get_level

int gpio_get_level(gpio_num_t gpio_num)
  • 参数
    • gpio_num:引脚号
  • 作用
    • 获取 GPIO 输入电平
  • 返回值
    • 0:低电平;1:高电平

如果引脚未配置为输入(或输入和输出),返回的值始终为 0。

2.8 gpio_set_direction

esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
  • 参数
    • gpio_num:引脚号
    • mode:要设置的模式,见第三小节
  • 作用
    • 配置 GPIO 方向,例如仅输出,仅输入,输出和输入
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.9 gpio_set_pull_mode

esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull_mode)
  • 参数
    • gpio_num:引脚号
    • pull_mode:GPIO 拉高/拉低模式,见第三小节
  • 作用
    • 配置 GPIO 上拉/下拉电阻
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误

2.10 gpio_isr_register

esp_err_t gpio_isr_register(void (*fn)(void*), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle)
  • 参数
    • fn:中断处理函数
    • arg :中断处理函数的参数
    • intr_alloc_flags:用于分配中断的标志。一个或多个(通过位或运算组合)ESP_INTR_FLAG_* 值。
    • handle:返回句柄的指针。如果非 NULL,这里将返回中断的句柄。

esp32_idf/esp-idf/components/esp_hw_support/include/esp_intr_alloc.h

//Keep the LEVELx values as they are here; they match up with (1<<level)
#define ESP_INTR_FLAG_LEVEL1        (1<<1)  ///< Accept a Level 1 interrupt vector (lowest priority)
#define ESP_INTR_FLAG_LEVEL2        (1<<2)  ///< Accept a Level 2 interrupt vector
#define ESP_INTR_FLAG_LEVEL3        (1<<3)  ///< Accept a Level 3 interrupt vector
#define ESP_INTR_FLAG_LEVEL4        (1<<4)  ///< Accept a Level 4 interrupt vector
#define ESP_INTR_FLAG_LEVEL5        (1<<5)  ///< Accept a Level 5 interrupt vector
#define ESP_INTR_FLAG_LEVEL6        (1<<6)  ///< Accept a Level 6 interrupt vector
#define ESP_INTR_FLAG_NMI           (1<<7)  ///< Accept a Level 7 interrupt vector (highest priority)
#define ESP_INTR_FLAG_SHARED        (1<<8)  ///< Interrupt can be shared between ISRs
#define ESP_INTR_FLAG_EDGE          (1<<9)  ///< Edge-triggered interrupt
#define ESP_INTR_FLAG_IRAM          (1<<10) ///< ISR can be called if cache is disabled
#define ESP_INTR_FLAG_INTRDISABLED  (1<<11) ///< Return with this interrupt disabled
  • 作用
    • 注册 GPIO 中断处理程序,该处理程序是一个 ISR。处理程序将被附加到运行此函数的相同 CPU 核心上。每当发生任何 GPIO 中断时,都会调用此 ISR。
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误
    • ESP_ERR_NOT_FOUND 在指定的标志下未找到可用的中断

2.11 gpio_install_isr_service

esp_err_t gpio_install_isr_service(int intr_alloc_flags)
  • 参数
    • intr_alloc_flags:分配中断时使用的标志。一个或多个(按 OR 运算)ESP_INTR_FLAG_* 值。见 2.10
  • 作用
    • 安装 GPIO 驱动程序的 ETS_GPIO_INTR_SOURCE ISR 处理程序服务,允许为每个引脚配置GPIO中断处理程序。
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误
    • ESP_ERR_NOT_FOUND 没有找到具有指定标志的空中断
    • ESP_ERR_INVALID_STATE ISR 服务未初始化。

此功能与 gpio_isr_register() 不兼容 - 如果使用该功能,将为所有 GPIO 中断注册一个全局中断服务程序(ISR)。如果使用此功能,中断服务提供了一个全局 GPIO ISR,通过 gpio_isr_handler_add() 函数注册单个引脚处理器。

2.12 gpio_uninstall_isr_service

void gpio_uninstall_isr_service(void)

卸载驱动的 GPIO ISR 服务,释放相关资源。

2.13 gpio_isr_handler_add

esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void* args)
  • 参数
    • gpio_num:引脚号
    • isr_handler:中断处理函数
    • args:中断处理函数的参数
  • 作用
    • 为相应的 GPIO 引脚添加 ISR 处理器。使用完 gpio_install_isr_service() 后,调用此函数以安装驱动程序的 GPIO ISR 服务。
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误
    • ESP_ERR_INVALID_STATE ISR 服务未初始化。

中断服务例行程序(ISR)处理器不再需要使用 IRAM_ATTR 进行声明,除非在为中断服务程序(ISR)分配 gpio_install_isr_service() 时传递 ESP_INTR_FLAG_IRAM 标志。

此 ISR 处理器将从 ISR 中调用。因此有一个堆栈大小限制(在 menuconfig 中可配置为“ISR 堆栈大小”)。与全局 GPIO 中断处理器相比,这个限制较小,因为多了一层间接性。

2.14 gpio_isr_handler_remove

esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num)
  • 参数
    • gpio_num:引脚号
  • 作用
    • 移除对应 GPIO 引脚的 ISR 处理器。
  • 返回值
    • ESP_OK 成功
    • ESP_ERR_INVALID_ARG 参数错误
    • ESP_ERR_INVALID_STATE ISR 服务未初始化。

3、枚举类型

选自文件:esp32_idf/esp-idf/components/hal/include/hal/gpio_types.h

3.1 gpio_mode_t

typedef enum {
    GPIO_MODE_DISABLE = GPIO_MODE_DEF_DISABLE,                                                         /* 禁用GPIO端口的输入和输出功能 */
    GPIO_MODE_INPUT = GPIO_MODE_DEF_INPUT,                                                             /* 输入模式 */
    GPIO_MODE_OUTPUT = GPIO_MODE_DEF_OUTPUT,                                                           /* 输出模式 */
    GPIO_MODE_OUTPUT_OD = ((GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)),                               /* 开漏模式,常用于与其他设备共享信号线的场景 */
    GPIO_MODE_INPUT_OUTPUT_OD = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT) | (GPIO_MODE_DEF_OD)), /* 同时作为输入和输出,并且具有开漏特性。这种组合模式常用于复杂的需求,如与外部设备双向通信 */
    GPIO_MODE_INPUT_OUTPUT = ((GPIO_MODE_DEF_INPUT) | (GPIO_MODE_DEF_OUTPUT)),                         /*同时作为输入和输出 */
} gpio_mode_t;

3.2 gpio_pullup_t

typedef enum {
    GPIO_PULLUP_DISABLE = 0x0,     /* 无上拉 */
    GPIO_PULLUP_ENABLE = 0x1,      /* 设置为上拉 */
} gpio_pullup_t;

3.3 gpio_pulldown_t

typedef enum {
    GPIO_PULLDOWN_DISABLE = 0x0,   /* 无下拉 */
    GPIO_PULLDOWN_ENABLE = 0x1,    /* 设置为下拉 */
} gpio_pulldown_t;

3.4 gpio_pull_mode_t

typedef enum {
    GPIO_PULLUP_ONLY,               /* 仅上拉 */
    GPIO_PULLDOWN_ONLY,             /* 仅下拉 */
    GPIO_PULLUP_PULLDOWN,           /* 同时配置为上拉和下拉 */
    GPIO_FLOATING,                  /* 浮动模式,即不施加任何上拉或下拉。
    								   引脚的电平状态是不确定的,通常用于测量或读取外部信号 */
} gpio_pull_mode_t;

3.5 gpio_int_type_t

typedef enum {
    GPIO_INTR_DISABLE = 0,     /* 禁用中断 */
    GPIO_INTR_POSEDGE = 1,     /* 上升沿触发 */
    GPIO_INTR_NEGEDGE = 2,     /* 下降沿触发 */
    GPIO_INTR_ANYEDGE = 3,     /* 上升沿和下降沿同时触发中断 */
    GPIO_INTR_LOW_LEVEL = 4,   /* 引脚低电平时触发 */
    GPIO_INTR_HIGH_LEVEL = 5,  /* 引脚高电平时触发 */
    GPIO_INTR_MAX,			   /* 通常用于循环或者判断是否超出范围而定义的最大值 */
} gpio_int_type_t;

三、实例操作

1、例一——简单的点灯程序

这一小节,以一个简单的点灯程序为例,来熟悉一下 ESP32-IDF GPIO 的使用。

创建程序相关见前:ESP32-IDF 在 Ubuntu 下的配置

例程代码如下:

#define LED1_GPIO GPIO_NUM_12

void led1_run_task(void)
{
	int gpio_level = 0;

	while(1)
	{
		gpio_level = !gpio_level;
		gpio_set_level(LED1_GPIO, gpio_level);
		vTaskDelay(pdMS_TO_TICKS(500));
	}
}

void app_main(void)
{
	gpio_config_t led_conf = {
		.pin_bit_mask = (1 << LED1_GPIO),
		.pull_up_en   = 1,
		.pull_down_en = GPIO_PULLDOWN_DISABLE,
		.mode         = GPIO_MODE_OUTPUT,
		.intr_type    = GPIO_INTR_DISABLE,
	};
	gpio_config(&led_conf);

	xTaskCreate((void *)led1_run_task, "led1", 1024 * 2, NULL, 0, NULL);
}

2、例二——添加中断

本例将读取外部按键 KEY 的状态,当按下 KEY 是窗口打印信息。

2.1 通过 GPIO 读取实现

这里通过 GPIO 读取 KEY 引脚来实现“中断”:

#define KEY_GPIO GPIO_NUM_9

void app_main(void)
{
    gpio_config_t key_conf = {
        .pin_bit_mask = (1ULL << KEY_GPIO),
       .mode = GPIO_MODE_INPUT,
       .pull_up_en = GPIO_PULLUP_ENABLE,
       .pull_down_en = GPIO_PULLDOWN_DISABLE,
       .intr_type = GPIO_INTR_POSEDGE,
    };

    gpio_config(&key_conf);

    while (1) {
        if (gpio_get_level(KEY_GPIO) == 0)
        {
            vTaskDelay(pdMS_TO_TICKS(10));
            while (gpio_get_level(KEY_GPIO) == 0);
            printf("KEY PRESSED\n");
        }
    }
}

2.2 通过中断函数实现

#define GPIO_INPUT_IO         9
#define GPIO_INPUT_PIN_SEL    1ULL<<GPIO_INPUT_IO
#define ESP_INTR_FLAG_DEFAULT 0

static QueueHandle_t gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void* arg)
{
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
}

static void gpio_task_example(void* arg)
{
    uint32_t io_num;
    for(;;) {
        if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
            printf("GPIO[%ld] intr, val: %d\n", (uint32_t)io_num, gpio_get_level(io_num));
        }
    }
}

void app_main(void)
{
    gpio_config_t gpio_conf = {
        .intr_type = GPIO_INTR_ANYEDGE,      // 上升、下降沿都产生中断
        .pin_bit_mask = GPIO_INPUT_PIN_SEL,  // bit mask of the pins, use GPIO0 here
        .mode = GPIO_MODE_INPUT,             // 设置输入模式
        .pull_up_en = 1,                     // 使能上拉
    };
    gpio_config(&gpio_conf);

    //create a queue to handle gpio event from isr
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //start gpio task
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    //install gpio isr service
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    
    //hook isr handler for specific gpio pin
    gpio_isr_handler_add(GPIO_INPUT_IO, gpio_isr_handler, (void*) GPIO_INPUT_IO);
}

标签:ESP,isr,ESP32,引脚,num,gpio,IDF,GPIO
From: https://blog.csdn.net/Teminator_/article/details/142991265

相关文章

  • esp32_lvgl_driver小缺陷
    问题背景最近在调试一个新屏幕的过程中,使用LVGL官方的lvgl_esp32_driver驱动,在我这个分辨率比较大(454x454)的屏幕下会出现,在分配完成buff后,若buff过大会出现,在刷屏的时候会这种警告。txdatatransfer>hardwaremaxsupportedlen研究了底层代码后发现在spi_master.c文件......
  • 基于乐鑫 ESP32-C3 的 Matter Light 实践
    背景介绍最近公司在研究Matter协议在智能家居领域的市场机会,考虑到易用性和文档支撑等方面,相比较Telink,产品部门对乐鑫的Matter-SDK更感兴趣,因而开展了一些测试工作,毕竟实践出真知嘛。......
  • ZYNQ使用XGPIO驱动外设模块(后半部分)
    目录注意重点:一、SDK代码开发部分:显示所需的字符编码:1.用于显示8x16的字符函数:2.绘制图片:3.清楚给定两个坐标之间的显示:4.显示16*32的阿拉伯数字字符:5.显示16*32的整型数字,最大显示到万位:Debug运行二、取模显示图片三、调试效果:注意重点:1.我们运行代码,注意,DEB......
  • 【ESP32】ESP32系列选型
    1.ESP32-P1.1ESP32-P4(32bitRISC-VMCU)ESP32-P4搭载双核RISC-V处理器,拥有AI指令扩展、先进的内存子系统,并集成高速外设。ESP32-P4专为高性能和高安全的应用设计,充分满足下一代嵌入式应用对人机界面支持、边缘计算能力和IO连接特性等方面提出的更高需求。性能ESP32......
  • the installation and usage of the dev environment of esp32
    theinstallationofthedevenvironmentofesp32someconditionusevscodesimplestepschoosethepulginsofidfthendownloadthepulginsandenterthemainpagechoosethefistchoicethenyouchoosethebersionofidfandthepathofitwaitpat......
  • 3-GPIO八大输出模式 推挽输出 与 开漏输出
    推挽输出与开漏输出GPIO有八大输出模式下图为每个GPIO口的基本结构:通过这张图来学习最右侧是I/O引脚,是从STM32引脚到GPIO口的导线,与其他芯片进行连接的线。芯片内部电路所能承受的电压有限,当未知的静电进入GPIO口,大于所能承受的电压,就会被上方的保护二极管导通,将电......
  • STM32与ESP32串口数据发送以及网页端数据实时显示和远程遥控
    目标:实现网页端速度实时显示以及可以通过点击页面按键达到对小车的位移方位控制。一、ESP32代码首先,需要让ESP32连接到WiFi,这样才能为后续的操作做准备。ssid="xxxxxx"password="xxxxxx"#WIFI连接defwifi_connect():wlan=network.WLAN(network.STA_IF)#STA模式......
  • ESP-IDF 学习 2 IO & interrupt 的使用
    APIofIO使用ESP-IDF的时候,不似STC单片机那样,它帮助我们集成了FreeRTOS,很少会直接访问寄存器,访问IO亦如此,所以我们调用它提供给我们的API就可以访问IO当前的level。相应的,我们对IO初始化的时候也不是访问IO配置寄存器来初始化IO的模式,是通过配置结构体对象,传......
  • ESP32移植Openharmony设备开发---(1)环境搭建
    第一章环境搭建1.下载ubuntu创建虚拟机内存分配建议8G硬盘大于200G                                                                下载ubuntu20.04复制特征码打开迅雷即可下载5F5E8848426......
  • ESP32移植Openharmony设备开发---(3)任务调度
    任务调度官方文档:OpenAtomOpenHarmony基本概念从系统角度看,任务是竞争系统资源的最小运行单元。任务可以使用或等待CPU、使用内存空间等系统资源,各任务的运行相互独立。OpenHarmonyLiteOS-M的任务模块可以给用户提供多个任务,实现任务间的切换,帮助用户管理业务程序流程。......