news 2026/8/30 15:33:03

重温STM32基础:关于GPIO(1)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
重温STM32基础:关于GPIO(1)

文章目录

  • 引脚电平
  • 输出模式
  • 输入模式
  • STM32中的GPIO
  • GPIO端口位的基本结构
    • 输入
      • 保护二极管
      • 4种输入模式
      • 施密特触发器
    • 输出
      • 3种设置输出值的操作方式
        • 读-改-写
        • 通过bit set/reset register(BSRR)
        • 位带操作
        • 三种方法总结
      • 4种输出模式
        • 开漏和推挽的选择
    • 输入输出电路同时工作?

最近借着江科大课程梳理了一下GPIO。

引脚电平

0~3.3V,部分可容忍5V。

  • 容忍5V的意思是可以容忍5V输入。下图中的表格截图来自于STM32F103的datasheet。FT代表能够容忍5V的电压,没有FT的就只能3.3V
  • 输出最多只能是3.3V,因为电源电压就是3.3V

    注:表格中的“主功能”是指引脚默认功能。通常和引脚名称一样。如果不一样,引脚的实际功能是主功能而不是引脚名称说的功能。

输出模式

输入模式控制端口输出高低电平

  • 驱动LED
  • 控制蜂鸣器
  • 模拟通信协议输出时序等
    如果控制的是功率比较大的设备,只需要加入驱动电路即可

输入模式

  • 读取端口的高低电平或电压
  • 读取按键输入
  • 外接模块电平信号输入
  • ADC电压采集(GPIO配置成模拟输入并配合ADC外设)
  • 模拟通信协议接收数据

STM32中的GPIO

  • 都是挂在APB2总线上。所以如果要使用GPIO,都需要通过RCC使能APB2的外设时钟(主要就是调用库函数中的“RCC_APB2PeriphClockCmd”)
  • 寄存器每一位都对应一个引脚
  • STM32的寄存器都是32位的,但是GPIO端口只有16位。所以图中的”寄存器“只有低16位对应有端口
  • 寄存器只负责存储数据,驱动器来增加驱动能力。

GPIO端口位的基本结构

输入

输入信号会经过的特殊部分:保护二极管 ->上拉/下拉电阻 ->施密特触发器 ->寄存器

保护二极管

保护二极管的工作机制,以标准GPIO为例(FT的GPIO类似):目的是对输入电压限幅

  • 上面的二极管提供过压保护:如果输入电压大于3.3V,则上面的二极管会被导通,这个大电流就会从上面出去,而不是进入芯片内部,从而保护芯片内部电路不受大电流的伤害。
  • 下面的二极管提供负压保护:如果输入电压为负(低于VSS),则下面连着VSS的二极管会被导通。VSS通常接地,则这个时候电流会从地流到外部设备,而不是从芯片内部流到外部设备。如果没有保护,内部电流会面临过流烧毁和电场击穿的风险
    要注意的是,这两个保护二极管是为了防止瞬态冲击,不能承受持续的大电流。如果外部长期存在负压或者大电流,需要靠其他器件来保护。

4种输入模式

上拉/下拉/浮空的本质是:给输入提供一个默认的输入电平。(当没有人(没有外部设备)明确告诉引脚"你是高电平"或"你是低电平"的时候,引脚自己应该处于什么状态?)

  1. 上拉输入:默认为高电平的模式。没有外部设备的时候,MCU读到的是高电平。当外部设备拉到低电平(比如接GND的按键按下),MCU可以读到低电平。这个模式是在检测外部”接地“作为有用信号的时候使用。
  2. 下拉输入:默认为低电平的模式。没有外部设备的时候,MCU读到的是低电平。当外部设备拉到高电平时(比如接VCC的按键按下),MCU可以读到高电平。
  3. 浮空输入:默认电平不确定。设置这个模式的时候,外部设备必须有一个连续的驱动源,不能出现悬空的状态。
  4. 模拟输入:配置成这个模式时,施密特触发器等全部断开。相当于从引脚直接接入片上外设,也就是ADC。所以当我们用ADC的时候把引脚配置成模拟输入就可以了。其他时候一般用不到这个模式。

施密特触发器

它的目的是对输入电压整形,效果是”迟滞“:只有高于高电平和低于低电平时,施密特触发器的输出才会变化。
它的前后信号分别被接入其他外设:

  • 它的前面是模拟输入,接到用模拟量的外设,主要是ADC
  • 它的后面是数字量,接到用数字量的外设

输出

3种设置输出值的操作方式

关注两个寄存器bit set/reset register 和 output data register(ODR)。ODR同时控制16个端口,且这个寄存器只能整体读写。所以如果需要单独控制其中某个端口而不影响其他,就需要一些特殊的操作方式。

读-改-写

读出寄存器的值 -> 按位或/与的方式更改某一位 -> 写回寄存器。对应C代码中的 |=和&=的操作。这种操作比较麻烦。
这种读-改-写的步骤还会有问题:这不是原子操作,会造成”竞争问题“。如果在第二步和第三步的时候中断突然发生,另一个代码也改写了这个ODR的其他位,那我们”写“的操作会把这另一个代码的修改覆盖。

通过bit set/reset register(BSRR)
  • 对某一位进行置1操作,在位设置的对应位写1即可,其他不需要操作的位写0。芯片内部电路自动讲ODR对应位置1,ODR的其他位(BSR里0的位置)保持不变。
  • 对某一位清零操作,在位清除的寄存器里对应位写1。这样内部电路就会把ODR的某一位清零。
位域作用
BR[15:0](高 16 位,Bit Reset)写 1 → 把 ODR 对应位清 0;写 0 → 无影响
BS[15:0](低 16 位,Bit Set)写 1 → 把 ODR 对应位置 1;写 0 → 无影响

这个方法是基于硬件的,整个过程是单周期、原子操作,所以不会有竞态。可以发现,我们是可以同时向指向同一个Port的BR和BS写1的(同时让它set和reset),但硬件规定是BS优先,所以结果确定,不会混乱。

位带操作

这是Cortex-M3/M4内核的一个硬件特性。STM32继承了这个特性。STM32专门分配有一段地址区域,这段地址隐射了RAM和外设寄存器所有的位。读写这段地址中的数据,就相当于读写所映射位置的某一位。具体来说
位带给每个位单独分配了一个 32 位的"替身地址"。比如(以下为假设)

  • ODR 寄存器的第 0 位 → 映射到地址 0x4001 1400
  • ODR 寄存器的第 1 位 → 映射到地址 0x4001 1404
    通过位带方式写ODR的第0位
*(volatileuint32_t*)0x40011400=1;// 向位带别名区写 1

硬件直接把这个值写进 ODR 的第 0 位,其他 31 个位完全不受影响。整个过程是原子的(不可中断),不存在"读-改-写"的竞态问题。但是比较麻烦的是需要计算别名地址。但是现在的一些HAL库可能已经做了封装。

三种方法总结

第二和第三种方法都不会有竞态问题。第二种方法只能用于GPIO,而第三种方法可以用于所有外设。可以把第二种方法看成GPIO外设的”专用位带“。

特性BSRR位带
操作对象只能改 GPIO 的 ODR可以改任何支持的寄存器/内存
操作方向只能写(置 1 或清 0)可读可写
写 0 的影响写 0 无影响(不会误改其他位)写 0 就是把该位清 0
使用方式向 32 位寄存器写值向映射的 32 位地址写值
本质外设硬件机制Cortex-M 内核总线机制

库函数用的是第二种方法。

4种输出模式

  1. 推挽输出:
    配置成这个模式的时候,
  • ODR配置成1时,P-MOS导通,N-MOS断开,外部接收3.3V
  • ODR配置成0时,P-MOS断开,N-MOS导通,外部接收低电平
    N-MOS和P-MOS是“互斥的,上关下开是连通3.3v给外部设备(推);上开下关就是把0V给外部设备(挽)。这种模式一般是驱动能够使用3.3V的外部设备而配置的。这个模式也叫”强推输出模式“,高低电平由STM32说了算。
  1. 开漏输出:上面的P-MOS无效。只有N-MOS工作。
  • ODR配置成1时,N-MOS断开,输出线相当于断开,是高阻模式
  • ODR配置成0时,N-MOS导通,输出线接到VSS,即输出低电平
    这种情况,只有低电平由驱动能力,高电平没有驱动能力(推挽输出模式是高低电平都有驱动能力)。可以作为通信协议的驱动模式,比如I2C的驱动引脚。开漏模式可以用于输出5V的电平信号,用于兼容一个5V的设备:比如在IO口外接一个上拉电阻到5V的电源。
  • ODR配置成1时,IO引脚由外部电阻拉高至5V
  • ODR配置成0时,IO引脚直接接到VSS
  1. 复用推挽输出,类似于普通的推挽输出,只是引脚电平时由片上外设控制的而不是ODR,如下图红圈是断开的
  2. 复用开漏输出,类似于普通的开漏输出,只是引脚电平时由片上外设控制的而不是ODR,如下图红圈是断开的

    可以发现,4种模式其实涉及两个维度的分类:
  • 复用和无复用:决定"谁控制引脚"(CPU 还是硬件外设)
  • 开漏和推挽:两种输出的物理结构。
开漏和推挽的选择
  • 必须开漏:
  1. I2C总线:I2C总线设计成高电平靠外部上拉电阻统一提供,所有设备只能拉低总线。如果用推挽输出,那么如果总线上一个设备输出高电平,一个输出低电平,就会造成短路。
  2. 需要电平转换:一个FT的引脚去驱动外部5V的设备(配置为开漏输出 + 外部 5V 上拉电阻)
  • 必须推挽:
  1. 一般数字输出(LED、蜂鸣器控制等):推挽输出高低电平都有驱动能力
  2. 高速通信(SPI或I2C):推挽输出的上升沿和下降沿都很陡峭(纳秒级),适合高速信号传输。如果用开漏 + 上拉电阻,RC 充电会让上升沿变得很慢,限制通信速率。
  3. 需要强高低电平驱动的场景:比如驱动 MOSFET 栅极、高速 CMOS 逻辑门等,推挽能提供更快的充放电能力。
  • 功耗考虑:
  1. 静态功耗:开漏输出高电平时,STM32引脚处于高阻态;设备引脚CMOS阻抗很高,但不是断开,但是此时上拉电阻还是会有微小的电流(漏电流)。如果总线上挂了很多设备,漏电流就会累计变得较大。当然,这还是很小的漏电流;当开漏输出低电平时,上拉电阻会持续耗电,功耗会非常高;相比之下,推挽输出没有持续的电阻通路,功耗较低。
  2. 瞬态电流:推完结构在电平翻转期间,可能会有一个短暂的PMOS和NMOS都导通的情况。这会在 VDD 和 GND 之间形成一个低阻通路,产生一个纳秒级的浪涌电流。单个引脚切换的时候不成问题,但是如果多个GPIO同时翻转,会产生多个这种瞬态电流,会有芯片功耗上升的情况。但开漏输出不会有这种GPIO电平翻转导通的问题。
  3. 上升沿功耗:开漏输出从低变高时,NMOS 截止,电容负载通过上拉电阻充电,这个充电电流持续流过电阻,单位时间内充电次数越多,动态功耗越大;而推挽输出是PMOS直接给电容负载充电,虽然也有功耗,但充电速度快、效率高,整体动态功耗通常更低。
  • 实际功耗考量
场景推荐模式原因
电池供电,引脚长期输出高电平推挽开漏上拉电阻会持续耗电
电池供电,引脚长期输出低电平开漏或推挽都可以开漏 NMOS 导通时功耗也很低
高速通信推挽边沿快,动态功耗效率更高
I2C 等必须开漏的总线开漏(无法选择)外部上拉电阻的功耗是必要代价

输入输出电路同时工作?

配置成输入模式的电路,可以发现,这个时候,输出部分的电路断开

配置成输出模式的电路,可以发现,这个时候,输如部分的电路还在,施密特触发器是on的!

所以,GPIO并不是只能作为输入,或者只能作为输出。STM32的GPIO电路里,输入检测电路和输出驱动电路是并行的,不是互斥的。至少,当配置成输出模式的时候,它还能读取。
总结来说

  • 配成输入时,输出端被强制断开,你无法驱动引脚。
  • 配成输出时,输入端并没有被断开,它一直"挂"在引脚上监听。此时(不用配置”输出模式“)仍然可以读取 IDR 寄存器,读到引脚上的实际电平
    其实,把”输入电路“理解成”引脚电压检测/监听“电路,就很好理解了。
    在输出模式下使用“输入”的作用
  1. 推挽输出时,验证输出是否真的出去了。
    比如你让引脚输出高电平,然后读 IDR:
  • 如果读到 1,则正常。
  • 如果读到 0,那么引脚可能被外部短路到地了,或者负载太大被拉低了。
  1. 开漏输出模式下引脚状态读取(重要应用)
    比如I2C 的 SDA 就是开漏输出 + 外部上拉。
  • 我们往ODR里写1时,是N-MOS断开,期望引脚靠外部上拉电阻变高
  • 我们往ODR里写0时,N-MOS导通,通常时把引脚拉到GND
    但是,我们如何知道实际引脚到底时高还是低?此时可以读IDR。在开漏模式下,总线上可能有其他设备把线拉低。你虽然"想"输出高电平(释放),但如果另一个设备把线拉低了,你读 IDR 就会读到 0。
    所以,在把GPIO配置成输出模式的时候,可以通过读取IDR来得到引脚的真实电平状态。
    当配置成“复用开漏/推挽输出”的时候,输入部分电路也是有效的,此时其他片上外设以及IDR也都是可以读取到引脚电平的(如“复用功能配置电路”图的绿圈所示)
    总结:只有当把GPIO配置成模拟输入的时候,输入模式部分电路会被关闭,其他7个模式中,输入部分电路一直是有效的。
    (还没完,且听下回继续补充)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 15:32:54

VC++集成Edge WebView2:现代Web技术与传统桌面应用的无缝融合

简介:本资源是一套面向Windows桌面应用开发者的VC WebView2集成实战方案,专为需要在原生C界面中嵌入现代Chromium内核浏览器功能的中高级开发者设计,解决传统IE内核WebView兼容性差、性能弱、API陈旧等核心痛点。压缩包共448个文件&#xff0…

作者头像 李华
网站建设 2026/8/30 15:29:51

传统搜索获客失效,拓氪科技如何用AI重构获客逻辑?

企业获客行业正迎来一场底层逻辑的颠覆性变革,其变革体量堪比传统线下会销全面转向搜索引擎竞价的时代级迭代。十余年前,国内企业完成了首轮获客数字化迁徙,将核心营销预算从线下户外广告、线下展会地推,转移至搜索引擎关键词竞价…

作者头像 李华
网站建设 2026/8/30 15:29:21

电子维修排查全攻略:从工具准备到实战案例与速查表

1. 排查前的基本功:工具和心态都别凑合 做电子维修这一行,最忌讳一上来就拿烙铁乱戳。拿到一块故障板子,先别急着通电,先把该准备的工具准备好,把该建立的排查思路建立起来。很多新手修不好板子,不是技术不…

作者头像 李华
网站建设 2026/8/30 15:27:28

学习Markdown系列 -- 在 Markdown 中使用 HTML

这听起来有点奇怪,不是吗?学习 Markdown 的全部意义就在于你不需要使用 HTML。问题在于,Markdown 不允许你做许多可以用 HTML 做的事情。诚然,你大多数时候并不需要做这些事情。甚至可能永远不需要。 不过,我发现有三件事我需要在 HTML 中做,而 Markdown 不支持: 在新浏…

作者头像 李华
网站建设 2026/8/30 15:25:16

AI平台腐烂:开发者如何避免被大模型API锁定?

在 AI 热潮中,开发者们争先恐后地接入大模型 API、构建 Agent 应用、搭配合适的提示词链。但很少有人停下来问一个更深层的问题: 当 AI 产业本身正在变成一座新的围墙花园时,开发者辛辛苦苦构建的应用,究竟是在积累自己的资产&am…

作者头像 李华