3、ESP32 GPIO基础与数字信号
各位同学,今天我们来聊聊ESP32最基础、也是最核心的东西——GPIO。说白了,就是芯片上那些可以编程控制的引脚。你想想看,一个单片机再厉害,如果没法跟外界打交道,那它就是一块废铁。GPIO就是ESP32的「手脚」,用来感知世界、控制设备。
3.1 什么是GPIO?
GPIO全称是General Purpose Input Output,通用输入输出口。每个GPIO引脚可以配置成输入模式,也可以配置成输出模式。输入就是读外部信号,比如按键按下没按下;输出就是让引脚输出高电平或低电平,比如点亮一个LED。
ESP32有34个GPIO引脚,编号从0到39。但注意,不是所有引脚都能随便用。我刚开始用ESP32时,就踩过这个坑——有些引脚内部已经连到了Flash或PSRAM,你强行拉高拉低,系统直接死机。嗯,这里要特别提醒:GPIO6到GPIO11是内部Flash的SPI接口,千万别动它们。
| 引脚范围 | 可用性 | 备注 |
|---|---|---|
| GPIO0 - GPIO5 | 可用 | 注意GPIO0上电电平影响启动模式 |
| GPIO6 - GPIO11 | 不可用 | 内部Flash占用,别碰 |
| GPIO12 - GPIO19 | 可用 | GPIO12上电电平影响Flash电压 |
| GPIO21 - GPIO23 | 可用 | 常用I2C、SPI引脚 |
| GPIO25 - GPIO27 | 可用 | 可作DAC输出 |
| GPIO32 - GPIO39 | 可用 | GPIO34-39只能输入,不能输出 |
3.2 三个核心函数
在Arduino框架下,操作GPIO只需要记住三个函数。我个人习惯把它们称为「GPIO三板斧」。
3.2.1 pinMode() —— 设置引脚模式
这个函数告诉ESP32,某个引脚是当输入用还是当输出用。语法很简单:
pinMode(pin, mode);
mode参数有三个常用选项:
- OUTPUT:输出模式,引脚可以输出高电平(3.3V)或低电平(0V)
- INPUT:输入模式,读取引脚上的电平状态
- INPUT_PULLUP:输入上拉模式,内部自动接一个上拉电阻
为什么要有INPUT_PULLUP?你想想看,如果按键一端接地,另一端接GPIO,当按键没按下时,引脚是悬空的,电平不确定。内部上拉电阻会把引脚默认拉到高电平,这样按键按下时读到低电平,逻辑就清晰了。
3.2.2 digitalWrite() —— 输出数字信号
这个函数让引脚输出高电平或低电平:
digitalWrite(pin, value);
value可以是:
- HIGH:输出3.3V高电平
- LOW:输出0V低电平
注意,ESP32的GPIO输出高电平是3.3V,不是5V。如果你要驱动5V的器件,需要加电平转换电路。我记得有次学员直接用ESP32去驱动一个5V继电器,结果继电器吸合不了,还差点烧了引脚。
3.2.3 digitalRead() —— 读取数字信号
这个函数读取引脚当前的电平状态:
int value = digitalRead(pin);
返回值是HIGH(1)或LOW(0)。
3.3 实战:按键控制LED
光说不练假把式。我们直接写一个完整的例子:按一下按键,LED亮;再按一下,LED灭。
硬件连接:
- LED正极接GPIO2,负极串联220Ω电阻到GND
- 按键一端接GPIO0,另一端接GND
代码实现:
// 引脚定义
const int ledPin = 2; // LED连接到GPIO2
const int buttonPin = 0; // 按键连接到GPIO0
int ledState = LOW; // LED当前状态
int buttonState; // 按键当前状态
int lastButtonState = HIGH; // 上一次按键状态
void setup() {
pinMode(ledPin, OUTPUT); // LED引脚设为输出
pinMode(buttonPin, INPUT_PULLUP); // 按键引脚设为输入上拉
Serial.begin(115200);
}
void loop() {
buttonState = digitalRead(buttonPin);
// 检测按键按下(电平从高变低)
if (buttonState == LOW && lastButtonState == HIGH) {
// 翻转LED状态
ledState = !ledState;
digitalWrite(ledPin, ledState);
Serial.print("LED状态:");
Serial.println(ledState == HIGH ? "亮" : "灭");
// 简单消抖延时
delay(50);
}
lastButtonState = buttonState;
}
🔑 关键点解析:
- 用了INPUT_PULLUP,按键没按下时读到HIGH,按下时读到LOW
- 通过检测电平变化(从高到低)来判断按键动作,而不是直接读电平
- 加了50ms延时做简单消抖。实际项目中我建议用定时器或状态机来做,更可靠
3.4 常见问题与调试技巧
做数字输入输出时,最容易出问题的就是电平匹配和引脚冲突。我分享几个实用技巧:
- 用串口打印调试:在代码里加Serial.println()打印引脚状态,比用万用表量方便多了
- 注意上电时序:有些外设上电瞬间会拉低引脚,导致ESP32误判。我一般会在setup()里加个500ms延时再初始化
- 不要超过额定电流:ESP32每个GPIO最大输出电流约40mA,整个芯片总电流不能超过200mA。驱动LED没问题,但别直接驱动电机
- 未使用的引脚:建议设为INPUT_PULLDOWN或输出低电平,避免悬空引入干扰
3.5 小结
这一章我们学了GPIO的三个核心函数:pinMode()配置模式、digitalWrite()输出信号、digitalRead()读取信号。通过按键控制LED的例子,你应该能体会到数字输入输出的本质——就是读0和1,写0和1。
下一章我们会用这些知识去驱动一个更有趣的外设——温湿度传感器DHT11。到时候你会发现,数字信号的世界远不止开关灯这么简单。
好,今天的课就到这里。动手把代码烧进去试试,有问题随时交流。