(3-1)基础外设使用(GPIO)

已写文章链接

本专栏主要内容是记录基于ESP32的开发工作,包括介绍 ESP32 基础知识、开发环境搭建、基础外设使用、蓝牙、WiFi 、与微信小程序联动等知识,达到自己动手做一些智能硬件的目的。
开发过程中主要参考官方资料,包括官网、规格书、参考手册、编程指南、驱动包等。
本专栏适合对ESP32感兴趣,想要找一个简单入手教程的同学。

ESP32 基础知识(已完成)

(1)ESP32基础知识

开发环境搭建(已完成)

(2-1)开发环境搭建(基于Arduino)
(2-2)开发环境搭建(基于VS Code+PlatformIO)
(2-3)开发环境搭建(基于ESP-IDF软件)

基础外设使用(已完成)

(3-1)基础外设使用(GPIO)
(3-2)基础外设使用(USART)

蓝牙(已完成)

(4)蓝牙使用(Classic BT+BLE)

WiFi(已完成)

(5)WiFi使用(STA模式)

微信小程序(已完成)

(6)微信小程序(配网和开关灯)


从本章开始介绍 ESP32 的基础外设使用,我在刚开始想用 ESP32 做一些东西时,发现网上比较多的资料大多是教大家如何搭建开发环境,而对于基础外设使用并没有过多介绍。等我自己使用Arduino之后,发现对于基础外设Arduino的针对 ESP32 开发板的示例相当完善,似乎没有单拿出来写的必要。但鉴于自己也是一个新手,还是把基础的外设示例跑一边,当做熟悉平台了。
搭建环境的时候看好多人说Arduino编译慢,以后大工程会卡顿。对我自己来说Arduino的示例足够好用,网上资料比较多。先用它实现一些基础的功能,等对平台熟悉了再决定要不要换到vscode + platformio或者ESP IDF
对于 ESP32 不太熟悉的可以看下面的文章。
(1)ESP32基础知识

硬件和软件版本

本文章使用的软硬件版本如下。
硬件

  • 开发板:ESP32-DevKitC-32E
  • 模组:ESP32-WROOM-32E
  • 芯片:ESP32-DOWD-V3

软件

  • 开发环境:Arduino IDE V2.2.1
  • ESP32 软件包:V2.0.11

ESP32 的 GPIO 基础知识

GPIO 的定义

以下定义来自于 ChatGPT

GPIO是通用输入/输出(General Purpose Input/Output)的缩写,是一种在嵌入式系统中常见的接口类型,用于与外部设备进行通信和控制。
GPIO可以分为以下几种分类:

  1. 数字GPIO:用于数字信号输入和输出。它们可以配置为输入以读取外部传感器或设备的状态,也可以配置为输出以控制外部设备。
  2. 模拟GPIO:有时也称为模拟输入/输出,用于传输模拟信号。与数字GPIO不同,模拟GPIO可以处理模拟信号,通常用于传感器读取或与模拟设备通信。
  3. 中断GPIO:允许设备在输入状态发生变化时产生中断。这样可以避免持续地轮询输入状态,而是通过中断方式告知处理器状态的变化。

使用GPIO的方法通常涉及以下步骤:

  1. 引脚配置:确定每个GPIO引脚的用途(输入或输出),以及引脚上使用的电压级别(高电平或低电平)。
  2. 初始化设置:在程序中初始化GPIO引脚,设置其方向(输入或输出)、电平状态等参数。
  3. 读取输入:如果GPIO被配置为输入,程序可以周期性地或基于事件来读取引脚的状态(高电平或低电平)。
  4. 写入输出:如果GPIO被配置为输出,程序可以控制引脚的状态,即设置引脚输出的电平状态(高电平或低电平)。
  5. 中断处理:如果支持中断,程序可以设置中断服务程序(ISR),在引脚状态发生变化时执行特定的操作。

在嵌入式系统中,GPIO常用于与各种外部设备进行通信,例如LED灯、按钮、传感器、电机等。使用GPIO需要根据具体的嵌入式系统和硬件平台来编写相应的驱动程序或使用相关的库函数进行控制和访问。

ESP32 的 GPIO 介绍

STM32H743IGT6为例,PB.8PB.9在其复用功能为AF4时只能作为I2C1_SCLI2C1_SDA,比如我想把PB.8PB.9当做IIS外设使用,那就不行,PB.8PB.9复用功能从AF0-AF15就没有IIS功能,要想使用IIS,得去找IIS外设对应的引脚。
image.png
但在 ESP32 中不是这样的。ESP32 芯片具有 34 个物理 GPIO 管脚(GPIO0 ~ GPIO19、GPIO21 ~ GPIO23、GPIO25 ~ GPIO27 和 GPIO32 ~ GPIO39)。每个管脚都可用作一个通用 IO,或连接一个内部的外设信号。通过 IO MUX、RTC IO MUX 和 GPIO 交换矩阵,可配置外设模块的输入信号来源于任何的 IO 管脚,并且外设模块的输出信号也可连接到任意 IO 管脚。这些模块共同组成了芯片的 IO 控制。
例如对于 ESP32,I2C 的默认引脚是 SDA (GPIO21) 和 SCL (GPIO22)。我们可以使用不同的引脚作为 如果您需要更改引脚,则默认的。 要更改引脚,我们必须在调用之前调用该函数。Wire.setPins(int sda, int scl);Wire.begin();

int sda_pin = 16; // GPIO16 as I2C SDA
int scl_pin = 17; // GPIO17 as I2C SCL

void setup()
{
    Wire.setPins(sda_pin, scl_pin); // Set the I2C pins before begin
    Wire.begin(); // join i2c bus (address optional for master)
}

image.png
像现在有些 STM32 芯片 USART 的 RX 和 TX 支持交换(可以避免硬件工程师把管脚连反的尴尬),但像 EPS32 这种外设引脚支持自定义这种方式还挺新颖的。
当然也不是所有外设引脚都支持自定义。以下是 ESP32 的基本外设支持表。专用 GPIO 就不支持自定义了。

类型功能
模数转换器专用 GPIO
DAC接口专用 GPIO
触摸传感器专用 GPIO
JTAG的专用 GPIO
SD/SDIO/MMC 主机控制器专用 GPIO
电机PWM任何 GPIO
SDIO/SPI从控制器专用 GPIO
串口任意 GPIO
I2C接口任何 GPIO
I2S的任何 GPIO
LED PWM调制任何 GPIO
RMT(RMT)任何 GPIO
通用IO输出接口任何 GPIO
并行 QSPI专用 GPIO
EMAC公司专用 GPIO
脉冲计数器任何 GPIO
TWAI公司任何 GPIO
USB接口专用 GPIO

** **还有一些限制,以下面的框图为例。

  • 某些 GPIO 仅是 INPUT。(例如 GPIO34、GPIO35、GPIO36 等)
  • 某些外设具有输出信号,必须在能够配置为 OUTPUT 的 GPIO 上使用。(例如 SPI_MOSI 引脚是输出引脚,就不能自定义到 GPIO34 上,因为 GPIO34 只能作为输入)
  • 一些外设,主要是高速外设、ADC、DAC、Touch 和 JTAG 使用专用的 GPIO 引脚。(例如 ADC 外设不支持引脚自定义。 想使用 ADC2_5 时,只能用 GPIO12,而不能自定义到 GPIO13)
  • 一些引脚用于连接模块上的闪存 - 这可以防止它们用于任何其他用途 - 如果外围设备路由到其中一个引脚,设备将无法启动。(例如标感叹号的 GPIO6-11)

image.png

硬件连接

按键引脚为 GPIO0。LED 灯引脚为 GPIO16。忘了怎么连的可以去看最前面的基础知识,也可以参考在wokwi中的连接(在wokwi中没找见电容,自己画了一个,实际电路中要注意)。
image.png
在这里插入图片描述
在这里插入图片描述

软件设计

GPIO 做输入

轮询方式

代码
#define LED 16
#define BUTTON 0

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT_PULLUP);
}

void loop() {
  if (digitalRead(BUTTON) == 0) 
  {
    delay(100);
    if(digitalRead(BUTTON) == 0) 
    {
      digitalWrite(LED, HIGH);
    }
  }
  else  if (digitalRead(BUTTON) == 1) 
    {
    delay(100);
    if(digitalRead(BUTTON) == 1) 
    {
      digitalWrite(LED, LOW);
    }
  }
}

工程

GPIO_INPUT_LOOP.7z

验证结果

实际拍的gif图过大,上传限制了,跟下面延时差不多,就不放了。
2023-12-09 17-52-50 (1).gif

中断方式

代码

中断加延时的方式不规范,仅测试验证使用。

#define LED 16
#define BUTTON 0

void ARDUINO_ISR_ATTR isr() {
 if (digitalRead(BUTTON) == 0) 
  {
    delay(100);
    if(digitalRead(BUTTON) == 0) 
    {
      digitalWrite(LED, HIGH);
    }
  }
  else  if (digitalRead(BUTTON) == 1) 
    {
    delay(100);
    if(digitalRead(BUTTON) == 1) 
    {
      digitalWrite(LED, LOW);
    }
  }
}

void setup() {
  pinMode(LED, OUTPUT);
  pinMode(BUTTON, INPUT);
  attachInterrupt(BUTTON, isr, CHANGE);
}

void loop() {
 
}

工程

GPIO_INPUT_INTERUPPT.7z

验证结果

结果跟GPIO 做输入章节一样。

GPIO 做输出

在上一个章节中,按键是 GPIO 作输入的例子,对 LED 灯的控制就是 GPIO 作输出的例子。此处不再赘述。

Arduino 库函数和 ESP32 库函数的对应

列举一下 arduino 和 esp32 库函数的对应关系。
在使用Arduino的 ESP32 库的时候,会看到我们调用的都是Arduino自己平台的库函数,比如改变 GPIO 电平的函数digitalWrite,而且示例代码与上面 GPIO 控制的完全一致。
image.png
但是 ESP32 的库函数,用于控制 GPIO 输出电平的函数不叫digitalWrite,而是gpio_set_level
image.png
那为什么使用Arduino的库函数也能控制 ESP32 的硬件呢?我们在Arduino的库函调用中寻找答案。从ESP32-hal-gpio.c中就能找见digitalWritegpio_set_level的调用关系了。同理可以找见pinModdigitalReadattachInterruptdetachInterrupt等,此处不再一一列举。
image.png
在这里插入图片描述

不知道ESP32-hal-gpio.c文件名中的 HAL 是不是硬件抽象层Hardware Abstraction Layer的意思。看文件开头的描述,这个文件是 ESP32 官方维护的。而ESP32-hal-gpio.hArduino官方维护的。是Arduino官方负责给出针对 GPIO 外设的统一控制接口,而不同的开发板厂商负责具体实现?在此不做深入研究,后面碰到了再看。
image.png
image.png

  • 16
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

尽欢_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值