【Java程序员学ESP32】05 ESP-IDF代码学习 - generic_gpio

本文详细分析了ESP_IDF中关于GPIO中断的示例代码,包括配置GPIO、使用中断、FreeRTOS消息队列以及中断处理函数。主要函数如`gpio_isr_handler`、`gpio_task_example`和`main`函数在代码中的作用被解释,并展示了如何通过`gpio_config`结构体初始化GPIO设置,以及如何注册和管理中断服务。
摘要由CSDN通过智能技术生成

本文学习一下ESP_IDF的示例工程中 peripherals -> gpio -> generic_gpio的源码。

  1. 首先还是用配置好环境的Clion(可参考前面的文章)打开示例工程
    只需要添加 IDF_TARGET 的cmake配置,工程就可以编译了 👍
    在这里插入图片描述

  2. 看一下README文件,对工程的描述
    This test code shows how to configure GPIO and how to use it with interruption.
    这个测试代码用来展示如何配置GPIO以及如何使用中断。

  3. 功能看起来不复杂,来学习一下代码
    主要的源文件只有一个 gipo_example_main.c,具体来看下里面的函数

  • 一段宏定义,这里面主要熟悉一下第三行,1ULL<<GPIO_OUTPUT_IO_0 GPIO引脚的bit_mask,简单理解就是选择这个引脚号的GPIO。
#define GPIO_OUTPUT_IO_0    CONFIG_GPIO_OUTPUT_0
#define GPIO_OUTPUT_IO_1    CONFIG_GPIO_OUTPUT_1
#define GPIO_OUTPUT_PIN_SEL  ((1ULL<<GPIO_OUTPUT_IO_0) | (1ULL<<GPIO_OUTPUT_IO_1))
#define GPIO_INPUT_IO_0     CONFIG_GPIO_INPUT_0
#define GPIO_INPUT_IO_1     CONFIG_GPIO_INPUT_1
#define GPIO_INPUT_PIN_SEL  ((1ULL<<GPIO_INPUT_IO_0) | (1ULL<<GPIO_INPUT_IO_1))
#define ESP_INTR_FLAG_DEFAULT 0
  • 几个函数和FreeRTOS相关,xQueueSendFromISR 作用是向队列后增加一个消息,这个示例里消息就是GPIO的pin号。gpio_task_example 用来循环打印队列中的消息内容。
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[%"PRIu32"] intr, val: %d\n", io_num, gpio_get_level(io_num));
        }
    }
}
  • 最重要的是main函数了,先看第一段,这里是对gpio config结构体的初始化,通过gpio_config 函数加载配置
    //清空初始化结构体.
    gpio_config_t io_conf = {};
    //不使用中断
    io_conf.intr_type = GPIO_INTR_DISABLE;
    //设置GPIO为输出模式
    io_conf.mode = GPIO_MODE_OUTPUT;
    //设置GPIO引脚的bit mask,比如18
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    //禁用下拉模式
    io_conf.pull_down_en = 0;
    //禁用上拉模式
    io_conf.pull_up_en = 0;
    //配置 GPIO
    gpio_config(&io_conf);
    
	//中断类型为上边沿中断
    io_conf.intr_type = GPIO_INTR_POSEDGE;
    //设置GPIO引脚的bit mask
    io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    //设置GPIO为输入模式
    io_conf.mode = GPIO_MODE_INPUT;
    //设置GPIO为上来模式
    io_conf.pull_up_en = 1;
    gpio_config(&io_conf);
  • 下面一段主要展示了几个用来设置GPIO参数的函数,gpio_install_isr_service用来开启GPIO的中断服务,后面用gpio_isr_handler_add添加实际的中断处理方法
    //用来修改中断类型
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

    //创建一个FreeRTOS的消息队列
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //开启FreeRTOS任务
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);

    //注册gpio中断处理服务
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //为GPIO_INPUT_IO_0添加一个中断处理方法
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    //为GPIO_INPUT_IO_1添加一个中断处理方法
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);

    //删除再添加,这里只是为了演示函数功能,非必要.
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
  • 最后开始执行示例程序,设置GPIO_OUTPUT_IO_0GPIO_OUTPUT_IO_1,时钟周期进行递增计数,并用计数对2取模设置高低电平。
int cnt = 0;
    while(1) {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
    }
  1. 和以往一样编译烧录,观察一下控制台打印的结果
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值