ESP-IDF学习笔记-GPIO的简单使用
ESP32中的GPIO可以分为简单的GPIO和专用GPIO,这里记录普通GPIO的使用。每个管脚都可用作一个通用 IO,或连接一个内部外设信号。通过 GPIO 交换矩阵、IO MUX 和 RTC IO MUX,可配置外设模块的输入信号来源于任何的 GPIO 管脚,并且外设模块的输出信号也可连接到任意 GPIO 管脚。这些模块共同组成了芯片的输入输出控制。
一,GPIO配置
头文件:driver/gpio.h
GPIO配置分为结构体配置和函数配置。
结构体配置
函数原型:
1 | esp_err_t gpio_config(const gpio_config_t *pGPIOConfig); |
可配置GPIO‘的输入输出模式、上下拉、中断类型、引脚。
使用的gpio_config_t
结构体:
成员 | 类型 | 作用 | 典型值 |
---|---|---|---|
pin_bit_mask | uint64_t | 选择引脚,以位为单位选择 | 如(1 << 18)|(1 << 19) |
mode | gpio_mode_t | 选择输入输出模式 | GPIO_MODE_DISABLE |
pull_up_en | gpio_pullup_t | 选择是否上拉 | GPIO_PULLUP_DISABLE /GPIO_PULLUP_ENABLE |
pull_down_en | gpio_pulldown_t | 选择是否下拉 | GPIO_PULLDOWN_DISABLE /GPIO_PULLDOWN_ENABLE |
intr_type | gpio_int_type_t | 中断触发模式 | GPIO_INTR_DISABLE |
详细参数解析:
gpio_mode_t:
GPIO_MODE_DISABLE
:失能输入输出GPIO_MODE_INPUT
:输入模式GPIO_MODE_OUTPUT
:输出模式GPIO_MODE_OUTPUT_OD
:开漏输出模式GPIO_MODE_INPUT_OUTPUT_OD
:开漏输入输出模式GPIO_MODE_INPUT_OUTPUT
:输入输出模式
gpio_int_type_t:
GPIO_INTR_DISABLE
:禁止中断GPIO_INTR_POSEDGE
:上升沿中断GPIO_INTR_NEGEDGE
:下降沿中断GPIO_INTR_ANYEDGE
:边缘中断GGPIO_INTR_LOW_LEVEL
:低电平中断GPIO_INTR_HIGH_LEVEL
:高电平中断
pin_bit_mask:
该参数使用每个bit表示要操作的GPIO口,典型使用值如下:
1 | // 表示此配置对 GPIO2生效,因为这个64位数的第2位(从零开始)为1 |
使用例:
1 | gpio_config_t gpio={ |
使用gpio_reset_pin()
重置IO口。
’
函数配置
就是将上面的结构体分成了多个函数进行配置,这里不多讲,请自行参考官方文档。
1 | esp_err_t gpio_set_intr_type(gpio_num_t gpio_num, gpio_int_type_t intr_type); |
二,IO口的使用
设置IO口输出:
1 | esp_err_t gpio_set_level(gpio_num_t gpio_num, uint32_t level); |
读取IO口状态:
1 | int gpio_get_level(gpio_num_t gpio_num); |
当IO口没有设置为输入,则读取的值恒为0。
三,中断的使用
1,设置中断类型
通过结构体配置,或者使用gpio_set_intr_type()
函数设置触发中断的条件。
2,创建中断服务函数
创建形如以下的中断服务函数
1 | static QueueHandle_t gpio_evt_queue = NULL; |
这里使用的FreeRTOS的消息队列传递中断信息。因为GPIO中断在IRAM中工作,好处是在flash禁用的情况下也可以响应中断。且速度更快,对于这种频繁触发的中断是有利的。但是这个中断也因此无法使用printf
等串口打印工作,需要转入其他Task中执行。详见官网API参考—— 中断分配Interrupt Allocation
3,创建中断处理任务函数
1 | static void gpio_task_example(void* arg) |
4,安装中断服务
1 | esp_err_t gpio_install_isr_service(int intr_alloc_flags); |
参数:
intr_alloc_flags – Flags used to allocate the interrupt. One or multiple (ORred) ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
该函数与gpio_isr_register()
不兼容。gpio_isr_register()
会创建一个中断服务函数处理全部的中断,用户需要在这个处理函数中分辨IO口分别处理。而使用这个函数,会用gpio_isr_register()
创建一个设置好的中断服务函数,分辨IO口的任务已经写好,使用gpio_isr_handler_add()
添加每个中断的服务函数。
相应的有移除函数。
1 | void gpio_uninstall_isr_service(void); |
5,为每个IO口添加handle
1 | esp_err_t gpio_isr_handler_add(gpio_num_t gpio_num, gpio_isr_t isr_handler, void *args); |
其中**args
是上面创建的中断服务函数传入**的参数。
该函数需要在gpio_install_isr_service()
后调用。使用该函数添加的服务函数不在需要使用IRAM_ATTR,除非在使用gpio_install_isr_service()
时设置了ESP_INTR_FLAG_IRAM
。
删除函数:
1 | esp_err_t gpio_isr_handler_remove(gpio_num_t gpio_num); |
6,开启任务
1 | xTaskCreate(gpio_task_example, "gpio_task_example", 2048, NULL, 10, NULL); |
注意,上面用到的FreeRTOS的API需要引入相应头文件。
1 |
一个例子:
1 |
|