ESP32 IDF Development Driver Chapter 5 GPIO and External Interrupt Explanation

ESP32 IDF Development Driver Chapter 5 GPIO and External Interrupt Explanation

  • 1 Introduction
  • 2. Principle
  • 3. Related functions
  • 4. Software design
  • 5. Example analysis
  • 6. The following are the debugging results:


Don’t get lost-Navigation bar
Quickly navigate to find what you want (article directory)


If this article is useful to you, please like and save it. Your support is the motivation for the blogger to persist.

1. Foreword

This chapter will introduce esp32 hardware related operations and briefly introduce the simple application of FreeRTOS API in IDF. For detailed explanation of FreeRTOS, please refer to [Armbbs] FreeRTOS operating system tutorial: http://www.armbbs.cn/forum .php?mod=viewthread &tid=17658

Learning purposes of this chapter:
①Learn ESP32 GPIO input/output configuration
② Master the use of ESP32 GPIO interrupt API
③Learn task creation and message queue of FreeRTOS API

2. Principle

Introduction to the GPIO interface of ESP32:
The ESP32 chip has 40 physical GPIO pins. Some GPIO pins are unavailable or do not have corresponding pins on the chip package (see Technical Reference Manual). Each pin can be used as a general-purpose I/O or can be connected to internal peripheral signals. Note that GPIO6-11 is normally used for SPI flash (not available).
GPIO34-39 can only be set to input mode and has no software pull-up or pull-down functionality. Separate “RTC GPIO” support is provided, which works when the GPIO is routed to the “RTC” low-power and analog subsystem. These pin functions can be used when in deep sleep, running an ultra-low power coprocessor, or using analog functions such as ADC/DAC/etc.

3. Related functions

For GPIO related functions, please refer to driver/include/driver/gpio.h
①, gpio_config GPIO general configuration.

/********************************************** *************************
* Function: gpio_config
* Description: Configure GPIO mode, pull-up, pull-down, IntrType
* Parameter: pGPIOConfig: pointer to the GPIO configuration structure
* Return: ESP_OK success, ESP_ERR_INVALID_ARG parameter error
* Remark:
*************************************************** **********************/
esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)

②, gpio_reset_pin reset gpio to default state

/********************************************** *************************
* Function: gpio_reset_pin
* Description: Reset gpio to default state (select gpio function, enable pull-up and disable input and output).
* Parameter: gpio_num: GPIO number.
* Return: always returns ESP_OK.
*Note: This feature also configures this pin's IOMUX as a GPIO function and disconnects any other peripheral output configured through the GPIO matrix.
*************************************************** **********************/
esp_err_t gpio_reset_pin(gpio_num_t gpio_num)

③, gpio_set_intr_type sets the interrupt trigger type

/********************************************** *************************
* Function: gpio_set_intr_type
* Description: Set the interrupt trigger type
* Parameters: gpio_num: GPIO number, intr_type interrupt type, select from gpio_int_type_t
* Return: ESP_OK successful, ESP_ERR_INVALID_ARG parameter error
* Remark:
*************************************************** **********************/
esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type);

④, esp_err_t gpio_intr_enable(gpio_num_t gpio_num); Enable GPIO module interrupt signal
⑤, esp_err_t gpio_intr_disable(gpio_num_t gpio_num); Disable GPIO module interrupt signal
⑥, gpio_set_level(gpio_num_t gpio_num, uint32_t level); GPIO set output level

/********************************************** *************************
* Function:
* Description: GPIO sets the output level
* Parameters: gpio_num: GPIO number, level 0: low; 1: high
* Return: ESP_OK successful, ESP_ERR_INVALID_ARG parameter error
* Remark:
*************************************************** **********************/
esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level);

⑦, gpio_get_level(gpio_num_t gpio_num); GPIO gets input level

/********************************************** *************************
* Function:
* Description: GPIO gets the input level
* Parameter: gpio_num: GPIO number
* Return: 0 GPIO input level is 0, 1 GPIO input level is 1
* Remark:
*************************************************** **********************/
int gpio_get_level(gpio_num_t gpio_num);

⑧, esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode); Configure GPIO direction, such as output_only, input_only, output_and_input
⑨, esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull); configure GPIO pull-up/pull-down resistor
⑩. gpio_install_isr_service installs the driver’s GPIO ISR handler service

/********************************************** *************************
* Function:
* Description: Installs the driver's GPIO ISR handler service, which allows per-pin GPIO interrupt handlers.
* Parameter: intr_alloc_flags: Flags used to allocate interrupts
* Return: *-ESP_OK successful
           *-ESP_ERR_NO_MEM No memory to install this service
           * - ESP_ERR_INVALID_STATE ISR service installed.
           *-ESP_ERR_NOT_FOUND No idle interrupt with the specified flag found
           *-ESP_ERR_INVALID_ARG GPIO error
* Note: This function is not compatible with gpio_isr_register() - if used, a global ISR is registered for all GPIO interrupts.
* If this feature is used, the ISR service will provide a global GPIO ISR and pass gpio_isr_handler_add()
* Function registers each pin handler.
*************************************************** **********************/
esp_err_t gpio_install_isr_service(int intr_alloc_flags);

?, void gpio_uninstall_isr_service(void); Uninstall the driver’s GPIO ISR service to release related resources.
?, gpio_isr_register register GPIO interrupt handler

/********************************************** *************************
* Function:
* Description: Register GPIO interrupt handler
* Parameter: fn interrupt processing function.
* intr_alloc_flags is used to allocate interrupt flags*
* arg handler function parameters
* handle points to a pointer to the return handle. If non-NULL, the interrupted handle will be returned here.
* Return: *-ESP_OK successful;
 *-ESP_ERR_INVALID_ARG GPIO error
 *-ESP_ERR_NOT_FOUND No idle interrupt with the specified flag found
* Remark:
*************************************************** **********************/
esp_err_t gpio_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags, gpio_isr_handle_t *handle);

?, gpio_isr_handler_add adds an ISR handler for the corresponding GPIO pin

/********************************************** *************************
* Function:
* Description: Add an ISR handler for the corresponding GPIO pin.
* Parameters: * @param gpio_num GPIO number
   * @param isr_handler ISR processing function, used for the corresponding GPIO number.
   * @param args parameters for the ISR handler.
* Return: *-ESP_OK successful
         *-ESP_ERR_INVALID_STATE status error, the ISR service has not been initialized.
        *-ESP_ERR_INVALID_ARG parameter error
* Remark:
*************************************************** **********************/
esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args);

?, esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num); Remove the ISR handler of the corresponding GPIO pin.

?, FreeRTOS task creation

BaseType_t xTaskCreate(
TaskFunction_t pvTaskCode, /* task function */
const char * const pcName, /* task name */
unsigned short usStackDepth, /* task stack size, unit word, that is, 4 bytes */
void *pvParameters, /* task parameters */
UBaseType_t uxPriority, /* task priority */
TaskHandle_t *pvCreatedTask /* Task handle */
);

?, function xQueueCreate is used to create a message queue

QueueHandle_t xQueueCreate( UBaseType_t uxQueueLength, /* Number of messages */
UBaseType_t uxItemSize ); /* Size of each message in bytes */

?, Function xQueueReceive is used to receive data in the message queue

BaseType_t xQueueReceive(
QueueHandle_t xQueue, /* message queue handle */
void *pvBuffer, /* Buffer address for receiving message queue data */
TickType_t xTicksToWait /* Maximum waiting time for waiting for data in the message queue */
);

?, function xQueueSendFromISR is used to send messages in the interrupt service program

BaseType_t xQueueSendFromISR(
QueueHandle_t xQueue, /* message queue handle */
const void *pvItemToQueue, /* Data address to be passed */
BaseType_t *pxHigherPriorityTaskWoken /* Save the status of whether the high-priority task is awakened */
);

The function xQueueSend is used to send messages in tasks.

BaseType_t xQueueSend(
QueueHandle_t xQueue, /* message queue handle */
const void * pvItemToQueue, /* Data address to be passed */
TickType_t xTicksToWait /* Maximum waiting time to wait for space in the message queue */
);

4. Software design

1), initialize gpio_config_t structure
gpio_config_t structure parameters:

typedef struct {<!-- -->
    uint64_t pin_bit_mask; /*!< GPIO pin: Set the bit mask, each bit is mapped 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 pulldown */
    gpio_int_type_t intr_type; /*!< GPIO interrupt type */
} gpio_config_t;

gpio_int_type_t enumeration type

typedef enum {<!-- -->
    GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */
    GPIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type: rising edge */
    GPIO_INTR_NEGEDGE = 2, /*!< GPIO interrupt type: falling edge */
    GPIO_INTR_ANYEDGE = 3, /*!< GPIO interrupt type: both rising and falling edge */
    GPIO_INTR_LOW_LEVEL = 4, /*!< GPIO interrupt type: input low level trigger */
    GPIO_INTR_HIGH_LEVEL = 5, /*!< GPIO interrupt type: input high level trigger */
    GPIO_INTR_MAX,
} gpio_int_type_t;

The common format for initializing GPIO through an initialization structure is:

 gpio_config_t gpio_conf = {<!-- -->
        .intr_type = GPIO_PIN_INTR_DISABLE, //Disable interrupts
        .mode = GPIO_MODE_OUTPUT, //Set to output mode
        .pin_bit_mask = GPIO_OUTPUT_PIN_SEL, //Output the specified pin
        .pull_down_en = 0, //Disable pull-down
        .pull_up_en = 0, //Disable pull-up
    };

Set io interrupt configuration:
//Set IO interrupt
gpio_conf.intr_type = GPIO_PIN_INTR_POSEDGE;//Set rising edge interrupt
gpio_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;//Input the specified pin
gpio_conf.mode = GPIO_MODE_INPUT; //Set to input mode
gpio_conf.pull_up_en = 1; //Enable pull-up
gpio_config( & amp;gpio_conf);

Change the pin’s interrupt triggering mode to rising edge and falling edge:

gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE);

Install gpio interrupt service to receive all interrupt levels

gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);

Receive interrupt 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

Finally add the interrupt service routine:

 gpio_isr_handler_add(GPIO_INPUT_IO_1, gpio_isr_handler, (void*) GPIO_INPUT_IO_1);

5. Example analysis

Copy the previous project and rename it to gpio_example. Change the file name to gpio_example.C. Change the makefile file to gpio_example, and then copy the code to test.

/********************************************** ************************
* File name: gpio_example.c
*               founder:            
* Creation date:
* Modified by:
* Modification date:
* Version number: V1.1
*               Remark:
*               company:
*************************************************** ******************/
#include 
#include 
#include 
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

/****************************************************** ************************
  *This test code shows how to configure gpio and how to use gpio interrupts.
  *
  * GPIO status:
  * GPIO18: output
  * GPIO19: output
  *GPIO4: input, pull-up, rising edge and falling edge interrupt
  * GPIO5: input, pull-up, rising edge interrupt.
  *test:
  *Connect GPIO18 to GPIO4
  *Connect GPIO19 to GPIO5
  * Generate pulses on GPIO18/19, which triggers interrupts on GPIO4/5
 *************************************************** **********************/

#define GPIO_OUTPUT_IO_0 18
#define GPIO_OUTPUT_IO_1 19
#define GPIO_OUTPUT_PIN_SEL ((1ULL<
    uint32_t gpio_num = (uint32_t) arg;
    xQueueSendFromISR(gpio_evt_queue, & amp;gpio_num, NULL);
}
/****************************************************** **********************
* Function:
* Description: gpio task function
* Parameters:
* Return: None
* Remark:
*************************************************** **********************/
static void vTaskGpio(void* arg)
{
    uint32_t io_num;
    for(;;) {
        //Receive the message sent by the interrupt program
        if(xQueueReceive(gpio_evt_queue, & amp;io_num, portMAX_DELAY))
        {
            printf("GPIO[%d] intr, val: %d\
", io_num, gpio_get_level(io_num));
        }
    }
}
/****************************************************** **********************
* Function:
* Description: Main function
* Parameters:
* Return: None
* Remark:
*************************************************** **********************/
void app_main(void)
{
    //Set IO output
    gpio_config_t gpio_conf = {<!-- -->
        .intr_type = GPIO_PIN_INTR_DISABLE, //Disable interrupts
        .mode = GPIO_MODE_OUTPUT, //Set to output mode
        .pin_bit_mask = GPIO_OUTPUT_PIN_SEL, //Output the specified pin
        .pull_down_en = 0, //Disable pull-down
        .pull_up_en = 0, //Disable pull-up
    };
    gpio_config( & amp;gpio_conf);

    //Set IO interrupt
    gpio_conf.intr_type = GPIO_PIN_INTR_POSEDGE;//Set rising edge interrupt
    gpio_conf.pin_bit_mask = GPIO_INPUT_PIN_SEL;//Input the specified pin
    gpio_conf.mode = GPIO_MODE_INPUT; //Set to input mode
    gpio_conf.pull_up_en = 1; //Enable pull-up
    gpio_config( & amp;gpio_conf);

    gpio_set_intr_type(GPIO_INPUT_IO_0, GPIO_INTR_ANYEDGE); //Change the pin's interrupt triggering mode to rising edge and falling edge
    //Create queue
    gpio_evt_queue = xQueueCreate(10, sizeof(uint32_t));
    //Create task
    xTaskCreate(vTaskGpio, //Task function
            "vTaskGpio", // task name
            2048, // Task stack size, unit word, that is, 4 bytes
            NULL, //Task parameters
            2, //Task priority
            NULL); //Task handle

    //Install gpio interrupt service and receive all interrupt levels
    gpio_install_isr_service(ESP_INTR_FLAG_LEVEL1);
    //Specify the pin as an ISR interrupt pin and add an interrupt service routine
    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);

    //Delete interrupt pin
    gpio_isr_handler_remove(GPIO_INPUT_IO_0);
    //Add interrupt service routine again
    gpio_isr_handler_add(GPIO_INPUT_IO_0, gpio_isr_handler, (void*) GPIO_INPUT_IO_0);

    int gpio_io = 0;
    while(1) {
        gpio_io = !gpio_io;
        printf("GPIO_OUTPUT_IO_0_1: %d\
", gpio_io);
        gpio_set_level(GPIO_OUTPUT_IO_0, gpio_io);
        gpio_set_level(GPIO_OUTPUT_IO_1, gpio_io);
        vTaskDelay(1000/portTICK_RATE_MS);

    }
}

6. The following are the debugging results:


All article source codes: https://download.csdn.net/download/lu330274924/88518092