云计算百科
云计算领域专业知识百科平台

STM32的GPIO位结构详解

对于学习STM32时,GPIO是一个最常用的一个结构,帮助实现了输入输出控制、上拉/下拉电阻、推挽/开漏等功能。但尽管十分常用,但如果没有好好的深入了解这一功能结构。在之后的STM32学习中时常会碰到配置GPIO引脚但纠结于要用开漏,推挽,还是复用等一系列问题,好像掌握了,但却又不知道如何去判断使用。因此,我直接从最底层的电路结构开始,详细讲述GPIO。

1.钳位保护二极管:结构、电性与原理

+3.3V (VDD)
|
┌──┴──┐
│ D1↑ │ ← 保护上拉二极管(正向:阳极→阴极)
I/O Pin ──┤ ├──→ 内部逻辑
│ D2↓ │ ← 保护下拉二极管(反向:阴极→阳极)
└──┬──┘
|
GND

工作原理:

当 输入电压 > VDD + Vf ≈ 3.3 + 0.6 = 3.9V:

上方二极管 D1 正向导通,电流流向芯片内部 VDD,防止高压损坏内部逻辑电路

当 输入电压 < VSS – Vf ≈ 0V – 0.6V = -0.6V:

下方二极管 D2 正向导通,把异常负电压释放到地(VSS)

可能大家会问,vf是什么

Vf = 正向导通压降(Forward Voltage)

对于硅二极管,Vf ≈ 0.6~0.7V

表示当二极管阳极比阴极高约0.6V,它就会导通,允许电流流过

它的作用:

抵御静电放电(ESD)

抵御高电压误触(例如误接 5V)

保证引脚输入不会烧毁内部 MOSFET 栅极

注意:

这些二极管只能承受mA 级别电流(短时间)

如果长时间高压接入,会导致 VDD 被拖高,整个芯片不稳定或损坏

若你需要外接 5V 信号,应在串口前加 限流电阻(如 330Ω) 或光耦/电平转换芯片

2.上拉 / 下拉电阻与开关

VDD GND
| |
┃30kΩ ┃30kΩ
| |
┌─┴─────┐ ┌──────┴─┐
│上拉开关│ │下拉开关│
└──┬────┘ └────┬──┘
| |
└───GPIO 引脚───┘

它的作用:

在输入状态下,引脚可能接了按钮、传感器,有时候没有接任何东西

如果悬空,电平状态是不确定的 → 导致输入一直抖动或变化

上拉使其默认电平为高,下拉使其默认为低

稳定电平是数字逻辑正常运行的前提条件

开关控制原理

每条电阻前面有个 MOSFET 开关

由 PUPDR 寄存器控制导通:

00:全部关闭(浮空输入)

01:上拉开关导通

10:下拉开关导通

 注意事项:

这些上/下拉是内部电阻,阻值较大(30~50kΩ)

不适合做电流负载,只是用于逻辑维持

开漏模式下,必须配合外部上拉或开启内部上拉

GPIO模式外部连接推荐电阻类型原因
输入模式 按键-GND 上拉电阻 松手时不悬空
输入模式 按键-VCC 下拉电阻 松手时不悬空
输入模式 集电极/光耦输出 上拉电阻 拉成高电平
输出模式(开漏) 接信号线/I²C 上拉电阻 提供高电平能力
输出模式(推挽) 不需要电阻 主动输出,电平稳定

总结

只有“悬空”才需要“拉”,只有“不能主动高”才需要“上拉”
推挽不用拉,输入/开漏必须拉!

3.TTL施密特触发器

施密特触发器的本质:

是一种带滞回特性的电压比较器。
它的作用是:避免输入信号在电平变化临界点抖动时产生多次误触发。

滞回特性图

(自己画了个小图便于理解)

滞回解释:

上升时要超过 高门槛(V_H)才认为是 1

下降时要低于 低门槛(V_L)才认为是 0

中间的电压变化不改变输出,避免毛刺、抖动

为什么 STM32 GPIO 输入必须使用施密特触发器

假设你用 GPIO 检测按钮输入:

按钮抬起/按下瞬间,可能存在抖动或接触不良

电压可能在 1.5V 附近多次震荡

没有施密特触发器时,CPU可能每次读都不一样

使用施密特触发器后,输入稳定可靠

适应模拟输入或缓慢变化信号

不是所有数字输入都是方波!有些是缓慢变化的模拟信号:(可以参考我的小图)

电容充放电

长电缆信号延迟

没有滞回,系统会频繁抖动

施密特触发器提供了数字逻辑输入的“安全门槛”

现象 / 场景是否需要施密特触发器说明
按钮输入 必须有 有机械抖动,易误判
电容触发信号 必须有 信号变化慢
模拟信号采样 不要有 会影响 ADC 结果,应设置为模拟模式断开缓冲器
数字外设输入(USART、SPI) 必须有 抗干扰要求高
高速通信(USB、CAN) 会关闭缓冲器 专用引脚自带高速输入电路

4.输出驱动结构:P-MOS & N-MOS

VDD ──┬────────────┐
│ P-MOS │
└────▲───────┘

GPIO ─────→ 引脚

┌────▼───────┐
│ N-MOS │
└────────────┘

GND

P-MOS(上拉):

源极接 VDD,漏极接 GPIO

当栅极电压远低于源极时导通

即 G = 0V → 导通 → 引脚输出 VDD(高电平)

 N-MOS(下拉):

源极接 GND,漏极接 GPIO

当栅极电压远高于源极时导通

即 G = 3.3V → 导通 → 引脚接地(低电平)

推挽模式(两者交替导通):

输出高 → P-MOS ON, N-MOS OFF → 引脚 = VDD

输出低 → P-MOS OFF, N-MOS ON → 引脚 = GND

开漏模式(只用 N-MOS):

输出高 → N-MOS OFF → 悬空

输出低 → N-MOS ON → 拉低

它的作用:

是引脚能否提供强电平驱动的核心器件

确保引脚能输出干净、强劲、低阻抗的电平

所以说什么时候用推挽什么时候用开漏

我总结了一个常用规律

“我一个人控制一根线” → 用推挽
“很多人共用一根线” → 用开漏

场景类型模式判断口诀
控制负载(LED、电机、蜂鸣器) 推挽 我要“拉高也拉低”,就选推挽
跟别人共用一根数据线(I2C、1-wire) 开漏 多人一起用线,避免冲突,用开漏
连接 NPN 三极管/光耦/继电器 开漏 我要“只拉低”,对方自己上拉
通信(UART、SPI) 推挽 数字波形必须干净,高低都要出
多个从机/芯片连接一根中断线 开漏 多人发信号 → 只能拉低 → 开漏
STM32 控制 5V 设备(电平不兼容) 开漏 STM32 只能悬空,靠 5V 上拉

因此,总结一下。

我用 GPIO 输出一个信号 →
┌──我只用自己控制这根线?
│ ├──是 → 推挽!
│ └──否 →
│ ┌──有多个设备共用这根线?
│ │ └──是 → 开漏!
│ └──控制目标是集电极输入(如光耦)?
│ └──是 → 开漏!
└──我要输出 PWM、数字信号、UART? → 推挽!

5.输入输出寄存器

ODR:输出数据寄存器

控制输出状态(置1输出高,置0输出低)

通过逻辑控制 P-MOS/N-MOS 开关

IDR:输入数据寄存器

读取 TTL触发器输出的值

程序判断引脚是否为高电平或低电平

BSRR:原子置位/清零寄存器

写 1 到低16位 → 设置对应引脚为高

写 1 到高16位 → 清除对应引脚为低

一次性修改多个引脚而不会中断打断 → 原子操作

6.复用输入/输出控制模块

控制逻辑:

MODER 控制当前引脚模式:

00 = 输入

01 = 输出

10 = 复用功能

11 = 模拟

AFRL / AFRH 选择复用功能编号(0~15)

AF1 = TIM

AF7 = USART

AF4 = I2C(具体看STM32引脚手册)

它的作用:

实现 GPIO 引脚的“多功能多用途” → 极大提升资源利用率

每个引脚最多可复用 16 种不同外设通道

何时用呢

不由你手动控制电平,而是由外设控制这个引脚电平!

外设复用功能为什么必须复用?
USART(串口) TX 引脚 串口要自动发送数据,不再由你手动控制引脚高低
TIM(定时器) PWM 引脚 定时器自动输出脉冲波形
SPI(串行外设) MOSI、SCK 波形自动由 SPI 控制
CAN 总线 TX 引脚 高速协议必须由外设模块控制
I²C 总线 SDA、SCL 需要硬件产生 START、ACK、STOP 等条件

只要你的某个引脚需要被一个“硬件外设”控制电平变化,就必须配置成复用功能输出。

寄存器控制内容
MODER 控制引脚的模式(输入 / 输出 / 复用 / 模拟)
OTYPER 控制输出类型(推挽 / 开漏)
OSPEEDR 控制输出速度(低 / 中 / 高 / 极高)
PUPDR 控制是否上拉/下拉
IDR 输入数据读取
ODR 输出数据设置(当模式为输出时)
AFR[0]/AFR[1] 控制复用功能选择(AF0 ~ AF15)
结构模块功能控制方式为什么存在
钳位二极管 过压保护 无需控制 防止ESD烧毁内部
上下拉电阻 电平默认值 PUPDR 保证输入稳定
TTL触发器 电平采样 自动生效 将模拟变为数字电平
输入驱动器 连接外设 MODER+AFR 把IO信号输入功能模块
输出MOS结构 电平驱动 ODR/BSRR + OTYPER 驱动输出强电平
控制寄存器 软件接口 CPU读写 软件对硬件的唯一桥梁
复用控制 多用共享 MODER + AFRL/H 节省引脚实现多功能
赞(0)
未经允许不得转载:网硕互联帮助中心 » STM32的GPIO位结构详解
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!