GPIO 基础与数字信号采集
这一章我们聊聊最基础、也最常用的东西——GPIO。说白了,就是芯片的那些引脚怎么用。我见过不少新手,上来就写代码,结果板子烧了还不知道怎么回事。嗯,咱们从根上捋一遍。
GPIO 模式配置:输入与输出
ESP32 的 GPIO 引脚,可以配置成输入,也可以配置成输出。但有个坑——不是所有引脚都能随便用。比如 GPIO6~GPIO11 被内部 Flash 占着,你碰都不能碰。
| 模式 | 方向 | 典型应用 | 注意事项 |
|---|---|---|---|
| GPIO_MODE_OUTPUT | 输出 | 控制 LED、继电器 | 注意驱动电流,别超过 12mA |
| GPIO_MODE_INPUT | 输入 | 读取按键、传感器信号 | 浮空引脚容易误触发 |
| GPIO_MODE_INPUT_OUTPUT | 双向 | I2C 数据线、单总线 | 开漏模式需要外部上拉 |
我个人习惯,配置引脚时一定先看 ESP32 的数据手册。有一次我图省事,直接用了 GPIO2 做输入,结果发现它默认接了板载 LED,电平一直拉高,读到的数据全是 1。折腾了半天才反应过来。
按键消抖:硬件与软件方案
按键按下那一下,你以为是一次干净的电平变化?其实不是。机械触点在闭合的瞬间会弹跳好几次,时间大概 5~20ms。如果不处理,一次按键可能被识别成十几次。
我最早做项目时,直接用 while 循环延时消抖。后来发现,延时期间 CPU 啥也干不了,太浪费了。现在我的做法是——状态机 + 定时器。
硬件消抖
加一个 RC 低通滤波器,电容 0.1μF,电阻 10kΩ。简单粗暴,但有效。不过会增加 BOM 成本,板子空间也占地方。
软件消抖
这是主流做法。核心思路:检测到电平变化后,等 20ms 再读一次,确认电平没变才算有效。
// 简易消抖函数
int debounce_read(gpio_num_t pin) {
if (gpio_get_level(pin) == 0) {
vTaskDelay(pdMS_TO_TICKS(20)); // 等 20ms
if (gpio_get_level(pin) == 0) {
return 0; // 确认按下
}
}
return 1; // 未按下或抖动
}
人体红外传感器(PIR)数据读取
人体红外传感器,也叫 PIR 传感器。它检测的是人体发出的红外辐射变化。有人走过时,热释电元件会输出一个脉冲信号。
常用的型号是 HC-SR501。它有三个引脚:VCC、GND、OUT。输出是数字信号——有人就高电平,没人就低电平。
接线方式
- VCC → 3.3V(注意不是 5V,ESP32 的 GPIO 耐受 3.3V)
- GND → GND
- OUT → GPIO4(随便选,避开受限引脚就行)
读取逻辑
PIR 输出是数字信号,直接用 GPIO 读就行。但有个细节——传感器上电后有 30~60 秒的稳定期,期间输出不稳定。代码里要加一个初始化延时。
#include "driver/gpio.h"
#define PIR_PIN GPIO_NUM_4
void pir_init() {
gpio_set_direction(PIR_PIN, GPIO_MODE_INPUT);
gpio_set_pull_mode(PIR_PIN, GPIO_PULLDOWN_ONLY);
vTaskDelay(pdMS_TO_TICKS(60000)); // 等传感器稳定
}
int pir_read() {
return gpio_get_level(PIR_PIN); // 1: 有人, 0: 无人
}
你想想看,如果没加这个 60 秒延时,上电后立刻读数据,大概率读到乱跳的电平。很多新手在这里踩坑,以为传感器坏了。
知识结构总览
下面这张图,把 GPIO 配置、按键消抖、PIR 读取串在了一起。你可以把它当作本章的思维导图。
实战建议
如果你刚开始学,我建议你从按键消抖入手。找一块面包板,接一个按键,用示波器看看按下时的波形。亲眼看到那个抖动,比看十遍理论都管用。
PIR 传感器这块,调试时注意环境温度。夏天室温高,人体和环境的温差小,传感器灵敏度会下降。我有个项目在海南测试,大中午的 PIR 死活不触发,后来发现是温差不够。解决办法是调高 HC-SR501 背面的灵敏度旋钮。
好了,这一章的内容就这些。GPIO 看似简单,但它是所有外设交互的基础。把这里搞扎实了,后面学 I2C、SPI 会轻松很多。