Skip to content

04 ESP32 GPIO介绍及使用

本文以ESP32 WROOM 模块为例介绍ESP32 GPIO的使用。

WROOM模块引脚命名,及功能如下图。

ESP32外设包括:

  • 18 Analog-to-Digital Converter (ADC) channels
  • 3 SPI interfaces
  • 3 UART interfaces
  • 2 I2C interfaces
  • 16 PWM output channels
  • 2 Digital-to-Analog Converters (DAC)
  • 2 I2S interfaces
  • 10 Capacitive sensing GPIOs

Pin的输入输出功能

GPIO Input Output Notes
0 pulled up OK outputs PWM signal at boot
1 TX pin OK debug output at boot
2 OK OK connected to on-board LED
3 OK RX pin HIGH at boot
4 OK OK
5 OK OK outputs PWM signal at boot
6 x x connected to the integrated SPI flash
7 x x connected to the integrated SPI flash
8 x x connected to the integrated SPI flash
9 x x connected to the integrated SPI flash
10 x x connected to the integrated SPI flash
11 x x connected to the integrated SPI flash
12 OK OK boot fail if pulled high
13 OK OK
14 OK OK outputs PWM signal at boot
15 OK OK outputs PWM signal at boot
16 OK OK
17 OK OK
18 OK OK
19 OK OK
21 OK OK
22 OK OK
23 OK OK
25 OK OK
26 OK OK
27 OK OK
32 OK OK
33 OK OK
34 OK input only
35 OK input only
36 OK input only
39 OK input only

一、中断

1、中断触发方式

ESP32 Arduino 有以下四种触发方式:

  • LOW 低电平触发
  • CHANGE 电平变化
  • RISING 上升沿触发
  • FALLING 下降沿触发
  • HIGH 高电平触发

2、配置中断

在定义中断函数后,需要在 setup 函数配置中断函数

// interrupt=中断通道编号,function=中断函数,mode=中断触发模式 attachInterrupt(interrupt, function, mode);

// pin=中断引脚,function=中断函数,mode=中断触发模式 attachInterrupt(pin, function, mode);

如果在程序运行过程不需要使用外部中断了,可以用中断分离函数来取消这一中断设置:

detachInterrupt(interrupt); detachInterrupt(Pin);。

3、示例

void setup()
{
  // 初始化日志打印串口
  Serial.begin(115200);

  // 配置中断引脚
  pinMode(26, INPUT|PULLUP );

  // 检测到引脚 26 下降沿,触发中断函数 blink
  attachInterrupt(26, blink, FALLING);

  Serial.println("\nstart irq test");
}

void loop()
{

}

// 中断函数
void blink()
{
  Serial.println("IRQ");
}

二、IIC 使用

示例:

#include <Wire.h>

void setup() {
  // 启动 i2c 总线
  Wire.begin();

  // 初始化串口
  Serial.begin(9600);
}

int reading = 0;

void loop() {
  // step 1: 启动与从设备 #112 0x70 的数据交互
  Wire.beginTransmission(112);

  // 发送数据
  Wire.write(byte(0x00));
  Wire.write(byte(0x50));

  // 结束通信
  Wire.endTransmission();

  // step 2: 等待读数据
  delay(70);

  // step 3: 读取指定寄存器
  Wire.beginTransmission(112);
  Wire.write(byte(0x02));
  Wire.endTransmission();

  // step 4: 请求读 2 字节数据
  Wire.requestFrom(112, 2);

  // step 5: 接收数据
  if (2 <= Wire.available()) {
    reading = Wire.read();
    reading = reading << 8;
    reading |= Wire.read();
    Serial.println(reading);
  }

  delay(250);
}

三、SPI 使用简析

示例:

/* The ESP32 has four SPi buses, however as of right now only two of

* them are available to use, HSPI and VSPI. Simply using the SPI API 
* as illustrated in Arduino examples will use HSPI, leaving VSPI unused.
* 
* However if we simply intialise two instance of the SPI class for both
* of these buses both can be used. However when just using these the Arduino
* way only will actually be outputting at a time.
* 
* Logic analyser capture is in the same folder as this example as
* "multiple_bus_output.png"
* 
* created 30/04/2018 by Alistair Symonds
  */
* 

#include <SPI.h>

static const int spiClk = 1000000; // 1 MHz

//uninitalised pointers to SPI objects
SPIClass * vspi = NULL;
SPIClass * hspi = NULL;

void setup() {
  // 初始化 SPI 实例 VSPI、HSPI
  vspi = new SPIClass(VSPI);
  hspi = new SPIClass(HSPI);

  //clock miso mosi ss

  //使用默认 VSPI 引脚:SCLK = 18, MISO = 19, MOSI = 23, SS = 5
  vspi->begin();

  // alternatively route through GPIO pins of your choice
  //vspi->begin(0, 2, 4, 33); // SCLK, MISO, MOSI, SS

  //使用默认引脚初始化 HSPI
  //SCLK = 14, MISO = 12, MOSI = 13, SS = 15
  hspi->begin(); 

  //alternatively route through GPIO pins
  //hspi->begin(25, 26, 27, 32); //SCLK, MISO, MOSI, SS

  // 初始化 ss 片选引脚,默认为低电平
  pinMode(5, OUTPUT); //VSPI SS
  pinMode(15, OUTPUT); //HSPI SS

}

// the loop function runs over and over again until power down or reset
void loop() {
  //use the SPI buses
  vspiCommand();
  hspiCommand();
  delay(100);
}

void vspiCommand() {
  // 模拟数据
  byte data = 0b01010101;

  // 启动 VSPI 传输
  vspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(5, LOW);
  vspi->transfer(data);  
  digitalWrite(5, HIGH);
  vspi->endTransaction();
}

void hspiCommand() {
  byte stuff = 0b11001100;

  hspi->beginTransaction(SPISettings(spiClk, MSBFIRST, SPI_MODE0));
  digitalWrite(15, LOW);
  hspi->transfer(stuff);
  digitalWrite(15, HIGH);
  hspi->endTransaction();
}