启明云端分享| ESP32学习笔记参考RTC_GPIO操作及疑难问题解答

提示:作为Espressif(乐鑫科技)大中华区合作伙伴及sigmastar(厦门星宸)VAD合作伙伴,我们不仅用心整理了你在开发过程中可能会遇到的问题以及快速上手的简明教程供开发小伙伴参考。同时也用心整理了乐鑫及星宸科技的新产品、新方案的主要特点及应用!希望你能第一时间了解并快速用上好的方案和产品!

在这里插入图片描述


ESP32_GPIO

一、普通GPIO

ESP32 芯片有 34 个物理 GPIO pad。每个 pad 都可用作一个通用 IO,或连接一个内部的外设信号。IO_MUX、RTC IO_MUX 和 GPIO 交换矩阵用于将信号从外设传输至 GPIO pad。这些模块共同组成了芯片的 IO 控制。

GPIO 输出和输入中断示例:home/ymy/esp-idf/examples/peripherals/gpio/generic_gpio/

  • GPIO1、3最好单独留出来给串口通讯用
  • GPIO6、7、8、9、10、11最好单独留出来给Flash控制用
  • GPIO34、35、36、39只能输入没有上下(为了保证引脚在默认状态下,这4个引脚可以通过外接上下拉电阻方式来实现稳定的电平。)
  • pull-up(上拉)
  • PullDown(下拉)
  • IntrType(中断)
  • GPIO_PIN_INTR_POSEDGE(上升沿)
  • GPIO_INTR_POSEDGE(下降沿)
  • GPIO_INTR_ANYEDGE(无论是上升沿还是下降沿,系统会自动选择一个作为中断沿)

示例代码:

//函数声明
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

/**
 * Brief:
 * This test code shows how to configure gpio and how to use gpio interrupt.  //如何配置gpio和如何使用gpio中断。
 *
 * GPIO status:
 * GPIO18: output                                                             //GP1018推挽输出
 * GPIO19: output                                                             //GPI019推挽输出
 * GPIO4:  input, pulled up, interrupt from rising edge and falling edge      //GPI04从上升沿和下降沿输入、上拉、中断
 * GPIO5:  input, pulled up, interrupt from rising edge.                      //GPIO5输入,上拉,从上升沿中断
 *
 * Test:
 * Connect GPIO18 with GPIO4                                                  //连接GP1018和GPIO4
 * Connect GPIO19 with GPIO5                                                  //连接GP1019和GPIO5
 * Generate pulses on GPIO18/19, that triggers interrupt on GPIO4/5           //连接GP1019和GPIO5在GPI018/19上产生脉冲,触发GPIO4/5上的中断
 *
 */

#define GPIO_OUTPUT_IO_0 18                                                           //定义GPIO18为输出管脚0
#define GPIO_OUTPUT_IO_1 19                                                           //定义GPIO19为输出管脚1
#define GPIO_OUTPUT_PIN_SEL ((1ULL << GPIO_OUTPUT_IO_0) | (1ULL << GPIO_OUTPUT_IO_1)) //混合
#define GPIO_INPUT_IO_0 4                                                             //定义GPIO4为输入管脚0
#define GPIO_INPUT_IO_1 5                                                             //定义GPIO5为输入管脚1
#define GPIO_INPUT_PIN_SEL ((1ULL << GPIO_INPUT_IO_0) | (1ULL << GPIO_INPUT_IO_1))    //混合
#define ESP_INTR_FLAG_DEFAULT 0                                                       //中断标志清零

// 设置消息队列,用于传递中断的信息返回变量
static xQueueHandle gpio_evt_queue = NULL; //将空变量gpio_evt_queue定义为队列(xQueueHandle)

//中断处理函数
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
    uint32_t gpio_num = (uint32_t)arg;                  //获取传过来的GPIO的管脚号
    xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL); //向消息队列中投递数据,消息内容为GPIO的管脚号
}

// GPIO中断消息处理任务
static void gpio_task_example(void *arg)
{
    uint32_t io_num;
    for (;;)
    {
        // API函数:接收队列消息函数xQueueReceive(),在FreeRTOS的任务中可以通过函数xQueueReceive接收获取芯片的中断消息,因为此函数可以设置超时等待,直到消息队列中有消息存放或者设置的超时时间溢出。
        //接受gpio队列,并在读取完后删除队列
        if (xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) //通过xQueueReceive()函数获取芯片的中断消息、启用引脚的值、延时的时间。
        {
            printf("GPIO[%d] intr, val: %d\n", io_num, gpio_get_level(io_num)); //打印GPIO引脚 和 管脚输出值
        }
    }
}

//主函数
void app_main(void)
{
    //初始化GPIO18/19
    gpio_config_t io_conf1 = {
        .intr_type = GPIO_INTR_DISABLE,      // GPIO中断禁用
        .mode = GPIO_MODE_OUTPUT,            // GPIO置为输出模式
        .pin_bit_mask = GPIO_OUTPUT_PIN_SEL, //设置GPIO18为输出管脚0与GPIO19为输出管脚1为混合模式
        .pull_down_en = 0,                   //不设置GPIO下拉
        .pull_up_en = 0,                     //不设置GPIO上拉
    };
    gpio_config(&io_conf1); // gpio_config 的功能是配置GPIO引脚参数

    //初始化GPIO4/5
    gpio_config_t io_conf2;
    io_conf2.intr_type = GPIO_INTR_POSEDGE;     //上升沿,下升沿为:GPIO_INTR_NEGEDGE
    io_conf2.pin_bit_mask = GPIO_INPUT_PIN_SEL; //设置GPIO4为输出管脚0与GPIO5为输出管脚1为混合模式
    io_conf2.mode = GPIO_MODE_INPUT;            // GPIO置为输入模式
    io_conf2.pull_up_en = 1;                    //使能上拉
    gpio_config(&io_conf2);                     // gpio_config 的功能是配置GPIO引脚参数

    //改变gpio任意一个引脚中断(上升沿和下降沿中断)
    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));                       //创建一个存放队列数据的变量
    xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); //创建使能GPIO中断的任务

    //安装gpio中断驱动
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    //给指定的gpio绑定中断服务函数
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);
    gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void *)GPIO_INPUT_IO_1);

    //删除相应GPIO引脚的中断服务函数
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    //再一次给指定的gpio绑定中断服务函数
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void *)GPIO_INPUT_IO_0);

    //打印内存使用情况
    printf("Minimum free heap size: %d bytes\n", esp_get_minimum_free_heap_size());

    int cnt = 0;
    while (1)
    {
        printf("cnt: %d\n", cnt++);
        vTaskDelay(1000 / portTICK_RATE_MS);       //延时1s
        gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2); //设置输出低电平
        gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2); //设置输出低电平
    }
}

二、RTC_GPIO

  • 在 Deep-sleep 模式下,只有 RTC_GPIO 可保持工作。且仅有 RTC GPIO 可以作为唤醒源,而非数字 GPIO。
  • 18 个 RTC GPIO 管脚,由 ESP32 的 RTC 子系统控制。作为输出管脚时仍然能够在芯片处于 Deep-sleep 睡眠模式下保持输出电平值或者作为输入管脚使用时可以将芯片从 Deep-sleep 中唤醒。可参见《ESP32 技术参考手册》中的 “RTC_MUX 管脚清单”。
  • ULP 模式下 RTC_GPIO 的应用例程:esp-iot-solution/examples/ulp_examples
  • 原文链接:https://blog.csdn.net/Marchtwentytwo/article/details/122196199

总结

要想设置GPIO中断,需进行如下三步操作:

  • 将GPIO设置为输入模式:GPIO_INPUT_IO_x

  • 编写中断处理函数和中断处理任务:

//中断处理函数
static void IRAM_ATTR gpio_isr_handler(void *arg)
{
	...
}

// GPIO中断消息处理任务
static void gpio_task_example(void *arg)
{
    ...
}
  • 设置中断触发条件及回调函数:

    • GPIO_PIN_INTR_POSEDGE(上升沿)
    • GPIO_INTR_POSEDGE(下降沿)

疑难问题

一、在运行github下载的6.ESP32_MultiThread文件编译不了,原因为:CMakeLists.txt not found in project directory /home/ymy/ESP32_Code/2.Code/6.ESP32_MultiThread/6.ESP32_MultiThread?

答:由于UP主用的是arduino开发,所以在idf环境下不能编译,我想请问一下这个怎么转到IDF环境下编译?

arduino是一款IDE,编译方式跟IDF不一样,两边的工程不能互相编译,可以把arduino当成一个库

二、CMack是什么?CMackFiles又是什么?

答:

  • CMake是一个跨平台的安装(编译)工具。
  • CMackFiles是cmack文件,是编译过后生成的文件。

三、xTaskCreate是什么函数?

答:如果不知道此函数的作用,请先学习一下FreeRTOS

  • 如果任务是使用xTaskCreate()创建的,则需要从FreeRTOS的堆中自动分配RAM。
  • 如果使用xTaskCreateStatic()创建任务,则由应用程序编写器提供RAM,这将导致两个额外的函数参数,但允许在编译时静态分配RAM。

四、在自己修改了GPIO实例代码后编译出现错误,修改回来之后就可以了,但我不知道为什么我修改的程序会出bug?

答:原因是我将gpio_config_t io_conf;改写成了gpio_config_t io_conf (){}或是gpio_config_t io_conf ={},所以编译会出错.

在初始化声明的时候,结构体赋值结尾是逗号,而且声明变量的中括号后要加分号。

**注意:**修改好之后记得保存代码再编译.

方法一:

//初始化GPIO18/19
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE; //GPIO中断禁用
io_conf.mode = GPIO_MODE_OUTPUT; //GPIO置为输出模式
io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL; //设置GPIO18为输出管脚0与GPIO19为输出管脚1为混合模式
io_conf.pull_down_en = 0; //不设置GPIO下拉
io_conf.pull_up_en = 0; //不设置GPIO上拉
gpio_config(&io_conf); //gpio_config 的功能是配置GPIO引脚参数

//初始化GPIO4/5 io_conf.intr_type = GPIO_INTR_POSEDGE;
//下降沿,上升沿为:GPIO_PIN_INTR_POSEDGE io_conf.pin_bit_mask =
GPIO_INPUT_PIN_SEL; //设置GPIO4为输出管脚0与GPIO5为输出管脚1为混合模式 io_conf.mode =
GPIO_MODE_INPUT; //GPIO置为输入模式 io_conf.pull_up_en = 1;
//使能上拉 gpio_config(&io_conf); //gpio_config
的功能是配置GPIO引脚参数

方法二:

//初始化GPIO18/19
gpio_config_t io_conf1 = {
.intr_type = GPIO_INTR_DISABLE, // GPIO中断禁用
.mode = GPIO_MODE_OUTPUT, // GPIO置为输出模式
.pin_bit_mask = GPIO_OUTPUT_PIN_SEL, //设置GPIO18为输出管脚0与GPIO19为输出管脚1为混合模式
.pull_down_en = 0, //不设置GPIO下拉
.pull_up_en = 0, //不设置GPIO上拉
};
gpio_config(&io_conf1); // gpio_config 的功能是配置GPIO引脚参数

//初始化GPIO4/5 gpio_config_t io_conf2 = { io_conf2.intr_type =
GPIO_INTR_POSEDGE, //下降沿,上升沿为:GPIO_PIN_INTR_POSEDGE
io_conf2.pin_bit_mask = GPIO_INPUT_PIN_SEL, //设置GPIO4为输出管脚0与GPIO5为输出管脚1为混合模式
io_conf2.mode = GPIO_MODE_INPUT, // GPIO置为输入模式
io_conf2.pull_up_en = 1, //使能上拉 }; gpio_config(&io_conf2); // gpio_config 的功能是配置GPIO引脚参数

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值