• esp32的GPIO操作


    对于任何一款芯片,GPIO接口是其最基本的组成部分,也是一款芯片入门的最基本操作,下面论述下 关于esp32开发版的GPIO操作,本文中重点讲解下

    关于如何创建eclipse工程,并通过eclipse下载到esp32中去(本文的工程文件在esp-idf/example/periheral文件夹中gpio工程),这里就不再详细论述了,可以看前面的文章,本文重点讲解工程源码,现在讲代码分块粘贴如下,并进行讲解。

    本次操作比较简单,大致可以分为以下几个部分

    PART1;

    定义gpio口寄存器及一个空的xQueueHandle类型的返回信号量。

    #define GPIO_OUTPUT_IO_0    18
    #define GPIO_OUTPUT_IO_1    19
    #define GPIO_OUTPUT_PIN_SEL  ((1<<GPIO_OUTPUT_IO_0) | (1<<GPIO_OUTPUT_IO_1)//配置gpioout位寄存器

    #define GPIO_INPUT_IO_0 4 #define GPIO_INPUT_IO_1 5 #define GPIO_INPUT_PIN_SEL ((1<<GPIO_INPUT_IO_0) | (1<<GPIO_INPUT_IO_1)) #define ESP_INTR_FLAG_DEFAULT 0  //定义默认的中断标志为0 static xQueueHandle gpio_evt_queue = NULL;     //定义一个队列返回变量

    PART2:

    编写中断处理函数及信号输出任务

    static void IRAM_ATTR gpio_isr_handler(void* arg)
    {
        uint32_t gpio_num = (uint32_t) arg;
        xQueueSendFromISR(gpio_evt_queue, &gpio_num, NULL);
        //xQueueSendFromISR是发生消息插入到队列的后面,将gpio的io口数传递到队列中,关于xQueueSendFromISR函数的相关知识,可以自己查询API手册,本文最后也有相关讲解
    }
    
    static void gpio_task_example(void* arg)
    {
        uint32_t io_num;
        for(;;) {
            if(xQueueReceive(gpio_evt_queue, &io_num, portMAX_DELAY)) {
                //接受gpio队列,并在读取完后删除队列
                printf("GPIO[%d] intr, val: %d
    ", io_num, gpio_get_level(io_num));
                //将GPIO的信息打印输出
            }
        }
    }

    PART3:

    应用主程序

     1 void app_main()
     2 {
     3     gpio_config_t io_conf;
     4     //定义一个gpio_config类型的结构体,下面的都算对其进行的配置
     5     //disable interrupt
     6     io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
     7     //set as output mode
     8     io_conf.mode = GPIO_MODE_OUTPUT;
     9     //bit mask of the pins that you want to set,e.g.GPIO18/19
    10     io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    11     //disable pull-down mode
    12     io_conf.pull_down_en = 0;
    13     //disable pull-up mode
    14     io_conf.pull_up_en = 0;
    15     //configure GPIO with the given settings
    16     gpio_config(&io_conf);
    17 
    18     //interrupt of rising edge
    19     io_conf.intr_type = GPIO_PIN_INTR_POSEDGE;
    20     //bit mask of the pins, use GPIO4/5 here
    21     io_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;
    22     //set as input mode    
    23     io_conf.mode = GPIO_MODE_INPUT;
    24     //enable pull-up mode
    25     io_conf.pull_up_en = 1;
    26     gpio_config(&io_conf);
    27 
    28     //change gpio intrrupt type for one pin
    29     gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);
    30 
    31     //create a queue to handle gpio event from isr
    32     gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    33     //start gpio task
    34     xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL);
    35 //
    36     //install gpio isr service
    37     gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    38     //hook isr handler for specific gpio pin
    39     gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    40     //hook isr handler for specific gpio pin
    41     gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);
    42 
    43     //remove isr handler for gpio number.
    44     gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    45     //hook isr handler for specific gpio pin again
    46     gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);
    47 
    48     int cnt = 0;
    49     while(1) {
    50         printf("cnt: %d
    ", cnt++);
    51         vTaskDelay(1000 / portTICK_RATE_MS);
    52         gpio_set_level(GPIO_OUTPUT_IO_0, cnt % 2);
    53         gpio_set_level(GPIO_OUTPUT_IO_1, cnt % 2);
    54     }
    55 }

     app_main中第三行申明gpio配置的结构体实例,然后在其后对gpio的结构体进行配置,然后开启一个gpio_task_example的任务处理GPIO4或者GPIO5中断发来的消息,这里用到FreeRTOS操作系统的消息队列功能实现中断函数与用户任务之间的消息传递。

    在44,46行中调用函数给 GPIO4和GPIO5管脚添加中断处理函数,并在最后的while循环中每隔1s切换一次GPIO18、GPIO19的电平值,

    实验现象:

        对于本例子的实验例子,实验操作是,将程序烧写到esp32中后,将GPIO18->GPIO4,GPIO19->GPIO5(—>表示连接),然后打开minicom(任意串口调试软件),可以看到每隔一秒gpio输出一次信息。由于app_main中第29行修改了GPIO_INPUT_IO_0为GPIO_INTR_ANYEDGE(即GPIO18的中断方式,所以,GPIO18的中断会比19多一次)。实验输出如下图所示:

    小TIPS:

       对于不知道的变量,想要找到其定义,选中想要查询的变量,按下F3即可自动跳转到其定义处,同理,选中,按F4可以看到此变量或函数被谁调用了。

    相关知识:

    1、esp32函数API:gpio口的函数API

    2、FreeRTOS函数API:

    以下截图来自正点原子FreeRTOS开发手册

     

     

     

  • 相关阅读:
    C#:BackgroundWorker的简单使用
    C#:DataTable 操作
    树和二叉树
    Git下的标签
    python的高级应用
    字符串匹配的BF算法和KMP算法学习
    GitHub:多人协作下的分支处理
    Git:分支的创建、合并、管理和删除
    GitHub:创建和修改远程仓库
    Git:文件操作和历史回退
  • 原文地址:https://www.cnblogs.com/noticeable/p/7458292.html
Copyright © 2020-2023  润新知