GPIO 与上下拉电阻:为什么按键要接电阻
GreenTerminal
4 分钟阅读
按键必须接电阻(或使能芯片内部上下拉)的根本原因,是给输入引脚一个确定的电平。没有上下拉的 GPIO 输入脚是悬空的,它的电平会随环境噪声、温度甚至旁边走线的耦合随机跳变,MCU 读到的 0/1 毫无意义,既会误触发逻辑,也会因输入缓冲级反复翻转而白白耗电。这一点在量产设备里尤其致命:同一块板子在实验室正常,到了电磁环境复杂的现场就偶发误动作,根因往往就是某个输入脚忘了处理。
悬空输入为什么不可靠
CMOS 输入级的栅极阻抗极高,引脚上几乎没有电流流入。当外部什么都没接时,引脚像一根天线,感应到的电荷无处泄放,电平可能停在中间区,使输入缓冲器同时导通 PMOS 和 NMOS 两个管子,产生贯穿电流。经验上这种状态下静态电流可能比正常高几个量级,且读到的电平完全不可预测。
更麻烦的是,悬空引脚的电平处于亚稳态,哪怕只是用手靠近、吹一口气,读到的逻辑就会翻转。在按键这类慢速事件里,这种翻转会被软件当成一次误触发;在中断输入脚上,则可能引发无中生有的中断风暴。所以任何配置为输入的 GPIO,要么外部接电阻,要么使能内部上下拉,不允许长期浮空。
上下拉怎么接
上拉电阻把引脚在无外部驱动时拉到 VCC,按键一端接地,按下时引脚被拉到地。下拉则相反,引脚默认经电阻接地,按键接 VCC。两者电平逻辑相反,软件读取时取反即可。现代 MCU 几乎都在每个 GPIO 上集成可配置上下拉,典型阻值在 20kΩ 到 80kΩ 之间,由内部弱电阻实现,优点是省掉外部元件,缺点是阻值较大、抗扰一般。
以寄存器配置为例(伪代码,不依赖具体厂商):
// 将 PA0 配置为输入,使能内部上拉
GPIOA->DIR &= ~(1 << 0); // 方向:输入
GPIOA->PUD |= (1 << 0); // 上拉使能
// 读取:按下为 0,释放为 1
if ((GPIOA->IN & (1 << 0)) == 0) {
key_pressed();
}
若外部已有电阻,则关闭内部上下拉以省电;若追求更强的抗干扰,也可外部用 4.7kΩ 同时关闭内部弱上拉,得到更确定的电平。
电阻取值的边界
电阻太小,按键按下时电流过大(I = VCC/R),例如 3.3V 下用 1kΩ 会持续流过 3.3mA;电阻太大,引脚对噪声和漏电越敏感,长走线或潮湿环境下容易误判。经验上板内按键用 4.7kΩ 到 10kΩ 外部电阻,或直接使用内部弱上拉即可。需要注意,上拉电阻和引脚对地存在的寄生电容会形成 RC 延时,阻值越大按键释放后的上升沿越慢,对高速采样不是问题,但对极窄脉冲捕捉要留余量。
去抖的软件实现
机械触点闭合与断开瞬间,金属弹片会 bouncing 几毫秒到十几毫秒,期间电平反复跳变。简单做法是检测到变化后延时 10ms 到 20ms 再读一次确认;更稳的做法是用定时器每隔几毫秒采样,连续 N 次一致才认定状态变化。无论哪种,都不要把去抖延时写在中断里阻塞其他逻辑。
三个常被忽略的坑
第一,按键走线过长且靠近高频信号线时,即使有上下拉仍可能耦合干扰,必要时并联 100nF 电容做硬件滤波,代价是响应变慢。第二,低功耗设备睡眠时若保留内部上拉,该支路仍会缓慢漏电,深度睡眠场景应评估是否断开或改用外部更大阻值电阻。第三,输出脚如果配置成开漏且外部没有上拉,同样会出现无法拉高的现象,这类问题常被误以为是程序写错了电平。
浏览 0
点赞 0
评论 0