ESP32学习记录:
- esp32系列(1):Hello world, 初识esp32 搭建VScode下的esp32开发环境,hello esp32。
- esp32系列(2):工程结构学习,从新建工程到烧写程序 熟悉工程的文件结构,各文件的含义,编译流程。以及VScode的具体操作。
- esp32系列(3):GPIOGPIO信号传输(以简单GPIO输入输出、ADC、DAC为例) 学习ESP32 GPIO与外设的几种输入输出方式,通过两个简单的例子学习简单GPIO与RTC GPIO输入输出的代码实现。
- 1 ESP32 GPIO基本概念
- 1.1 通过 GPIO 交换矩阵的外设输入
- 1.2 通过 GPIO 交换矩阵的外设输出
- 1.3 直接I/O
- 1.4 RTC IO_MUX 输入输出
- 2 代码实现
- 2.1 简单 GPIO 输入输出实现
- 2.2 RTC GPIO 输入输出实现
ESP32 芯片有 34 个物理 GPIO pad(GPIO PAD号:0-19, 21-23, 25-27, 32-39。其中 GPIO 34-39 仅用作输入管脚,其他的既可以作为输入又可以作为输出管脚。)。每个 pad 都可用作一个通用 IO,或连接一个内部的外设信号。
IO_MUX、RTC IO_MUX 和 GPIO 交换矩阵用于将信号从外设传输至 GPIO pad。这些模块共同组成了芯片的 IO 控 制。
- IO_MUX 选择GPIO pad配置为GPIO(与交换矩阵连接)或者直连(更好的高频数字特性,用于高速信号)
- GPIO 交换矩阵 进行【外设输入输出】与【pad信号】之间的全交换。其实就是完pad的输入与输出信号的选择。
- RTC IO_MUX 控制GPIO pad的低功耗和模拟功能。
34个GPIO(X: 0-19,21-23,25-27,32-39) 获取 外设输入信号的索引号(Y: 0-18,23-36,39-58,61-90,95-124,140-155,164-181,190-195,198-206)
重点:把某个外设信号 Y 绑定到某个 GPIO pad X 的配置过程为:
- 在 GPIO 交换矩阵中配置外设信号Y的
GPIO_FUNCy_IN_SEL_CFG
寄存器:- 设置
GPIO_FUNCy_IN_SEL
字段为要读取的GPIO pad X
的值。清零其他 GPIO pad 的其他字段。
- 设置
- 在 GPIO 交换矩阵中配置 GPIO pad X 的
GPIO_FUNCx_OUT_SEL_CFG
寄存器、清零GPIO_ENABLE_DATA[x]
字段:- 要强制管脚的输出状态始终由
GPIO_ENABLE_DATA[x]
字段决定,则将GPIO_FUNCx_OUT_SEL_CFG
寄存器的GPIO_FUNCx_OEN_SEL
字段位置为 1。 GPIO_ENABLE_DATA[x]
字段在GPIO_ENABLE_REG
(GPIOs 0-31) 或GPIO_ENABLE1_REG
(GPIOs 32-39) 中,清零此位可以关闭 GPIO pad 的输出。
- 要强制管脚的输出状态始终由
- 配置 IO_MUX 寄存器来选择 GPIO 交换矩阵。配置 GPIO pad X 的
IO_MUX_x_REG
的过程如下:- 设置功能字段 (MCU_SEL) 为 GPIO X 的 IO_MUX 功能(所有管脚的 Function 2,数值为 2)。
- 置位 FUN_IE 使能输入。
- 置位或清零 FUN_WPU 和 FUN_WPD 位,使能或关闭内部上拉/下拉电阻器。 说明:
- 同一个输入 pad 上可以同时绑定多个内部 input_signals。
- 置位 GPIO_FUNCy_IN_INV_SEL 可以把输入的信号取反。
- 无需将输入信号绑定到一个 pad 也可以使外设读取恒低或恒高电平的输入值。实现方式为选择特定的 GPIO_FUNCy_IN_SEL 输入值而不是一个 GPIO 序号:
- 当 GPIO_FUNCy_IN_SEL 是 0x30 时, input_signal_x 始终为 0。
- 当 GPIO_FUNCy_IN_SEL 是 0x38 时, input_signal_x 始终为 1。 例子:把 RMT 外设通道 0 的输入信号 RMT_SIG_IN0_IDX(信号索引号 83)绑定到 GPIO15,请按照以下步骤操作(请注意 GPIO15 也叫做 MTDO 管脚):
- 将 GPIO_FUNC83_IN_SEL_CFG 寄存器的 GPIO_FUNC83_IN_SEL 字段设置为 15。
- 因为此信号是纯输入信号,置位 GPIO_FUNC15_OUT_SEL_CFG_REG 寄存器中的 GPIO_FUNC15_OEN_SEL 位。
- 清零 GPIO_ENABLE_REG 寄存器的 bit 15(GPIO_ENABLE_DATA[15] 字段)。
- 配置 IO_MUX_GPIO15 寄存器的 MCU_SEL 字段为 2 (GPIO function),同时置位 FUN_IE(使能输入模式)。
简单的GOIO输入:
- GPIO_IN_REG/GPIO_IN1_REG 寄存器存储着每一个 GPIO pad 的输入值。
- 任意 GPIO pin 的输入值都可以随时读取而无需为某一个外设信号配置 GPIO 交换矩阵。但是需要为 pad X 的 IO_MUX_x_REG 寄存器配置 FUN_IE 位以使能输入。
28 个 GPIO (X: 0-19, 21-23, 25-27, 32-33) 获取 外设信号(Y: 0-18, 23-37, 61-121,140-215, 224-228)
重点:输出外设信号 Y 到某一 GPIO pad X 的步骤为:
- 在 GPIO 交换矩阵里配置 GPIO X 的 GPIO_FUNCx_OUT_SEL_CFG 寄存器和 GPIO_ENABLE_DATA[x] 字段:
- 设置 GPIO_FUNCx_OUT_SEL_CFG 寄存器的 GPIO_FUNCx_OUT_SEL 字段为外设输出信号 Y 的索引号 (Y)。
- 要将信号强制使能为输出模式,将 GPIO pad X 的 GPIO_FUNCx_OUT_SEL_CFG 寄存器的GPIO_FUNCx_OEN_SEL 置位,并且将 GPIO_ENABLE_REG 寄存器的 GPIO_ENABLE_DATA[x] 字段置位。或者,将 GPIO_FUNCx_OEN_SEL 清零,此时输出使能信号由内部逻辑功能决定。
- GPIO_ENABLE_DATA[x] 字段在 GPIO_ENABLE_REG (GPIOs 0-31) 或 GPIO_ENABLE1_REG (GPIOs32-39) 中,清零此位可以关闭 GPIO pad 的输出。
- 要选择以开漏方式输出,可以设置 GPIO X 的 GPIO_PINx 寄存器中的 GPIO_PINx_PAD_DRIVER 位。
- 配置 IO_MUX 寄存器来选择 GPIO 交换矩阵。配置 GPIO pad X 的 IO_MUX_x_REG 的过程如下:
- 设置功能字段 (MCU_SEL) 为 GPIO X 的 IO_MUX 功能(所有管脚的 Function 2,数值为 2)。
- 设置 FUN_DRV 字段为特定的输出强度值 (0-3),值越大,输出驱动能力越强。
- 在开漏模式下,通过置位/清零 FUN_WPU 和 FUN_WPD 使能或关闭上拉/下拉电阻器。
说明:
- 某一个外设的输出信号可以同时从多个 pad 输出。
- 置位 GPIO_FUNCx_OUT_INV_SEL 可以把输出的信号取反。
简单的GOIO输出:
- GPIO 交换矩阵也可以用于简单 GPIO 输出。设置 GPIO_OUT_DATA 寄存器中某一位的值可以写入对应的 GPIO pad。
- 为实现某一 pad 的 GPIO 输出,设置 GPIO 交换矩阵 GPIO_FUNCx_OUT_SEL 寄存器为特定的外设索引值 256(0x100)。
从之前的总体输入输出结构框图可以看出,IO_MUX还有一些直接I/O信号。快速信号如以太网、 SDIO、 SPI、 JTAG、 UART 等会旁路 GPIO 交换矩阵以实现更好的高频数字特性。
1.4 RTC IO_MUX 输入输出18 个 GPIO 管脚具有低功耗(低功耗 RTC)性能和模拟功能,这些功能不经过IO_MUX 和 GPIO 交换矩阵,而是使用 RTC_MUX 将 I/O 指向 RTC 子系统。
当这些管脚被配置为 RTC GPIO 管脚,作为输出管脚时仍然能够在芯片处于 Deep-sleep 睡眠模式下保持输出 电平值或者作为输入管脚使用时可以将芯片从 Deep-sleep 中唤醒。
2 代码实现 2.1 简单 GPIO 输入输出实现实际的实现,ESP-IDF官方文档中将GPIO的设置封装成函数:gpio_config。
@path: gpio.h
@brief: GPIO通用配置函数,配置 GPIO 的模式,上拉,下拉,中断
@param: 一个指向** GPIO 配置结构体**的指针 pGPIOConfig
@return: ESP_OK:成功;ESP_ERR_INVALID_ARG:参数错误
esp_err_t gpio_config(const gpio_config_t *pGPIOConfig);
GPIO 配置结构体:
/**
* @brief Configuration parameters of GPIO pad for gpio_config function
*/
typedef struct {
uint64_t pin_bit_mask; /*!< GPIO pin: set with bit mask, each bit maps 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 pull-down */
gpio_int_type_t intr_type; /*!< GPIO interrupt type */
} gpio_config_t;
以配置GPIO1为输出、GPIO3为输入为例。代码为:
#include
#include
#include
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h" //portTICK_RATE_MS
#include "freertos/task.h" //vTaskDelay
/**
* Brief:
* 基本的GPIO输入输出学习
*
* GPIO status:
* GPIO1: output
* GPIO3: input
*
* Test:
* Connect GPIO1 with GPIO3
* Generate pulses on GPIO3, that connect to GPIO3
*
*/
#define GPIO_2 2
#define GPIO_4 4
void app_main(void)
{
// GPIO1
gpio_config_t io_conf = {}; //新建配置GPIO pad的gpio_config功能参数的结构体
io_conf.pin_bit_mask = (1ULL
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?