news 2026/5/9 0:28:11

STM(GPIO)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM(GPIO)

GPIO的输出

GPIO简介

  • GPIOGeneral Purpose Input Output)通用输入输出口,也就是我们俗称的IO口
  • 可配置为8种输入输出模式
  • 引脚电平:0V~3.3V,
    数据0就是低电平,也就是0V;数据1就是高电平,也就是3.3V

    部分引脚可容忍5V,容忍5V的意思是可以在这个端口输入5V的电压,也认为是高电平
    但是对于输出而言,最大就只能输出3.3V,因为供电就只有3.3V
    具体哪些端口能容忍5V,可以参考一下STM32的引脚定义,图中带FT(Five Tolerate)的,就是可以容忍5V的,不带FT的,就只能接入3.3V的电压
  • 输出模式下可控制端口输出高低电平,用以驱动LED、控制蜂鸣器、模拟通信协议输出时序等
    LED和蜂鸣器的程序现象,就使用到了GPIO的输出模式
    另外在其他的应用场景,只要是可以用高低电平来进行控制地方
    都可以用GPIO来完成。如果控制的是功率比较大的设备,只需要再加入驱动电路即可
    还可以用GPIO模拟通讯协议。比如I2C、SPI或者某个芯片特定的协议,都可以用GPIO的输出模式来模拟其中的输出时序部分
  • 输入模式下可读取端口的高低电平或电压,用于读取按键输入、外接模块电平信号输入、ADC电压采集、模拟通信协议接收数据等
    模拟通信协议时,接收通信线上的数据,也是靠GPIO的输入来完成的

STM32的GPIO的基本结构

在STM32中,所有的GPIO都是挂载在APB2外设总线上的

其中GPIO外设的名称是按照GPIOA、GPIOB、GPIOC等等这样来命名的

每个GPIO外设,总共有16的引脚,编号是从0到15

那GPIOA的第0号引脚,我们一般把它称作PA0,接着第1号就是PA1以此类推

在每个GPIO模块内,主要包含了寄存器和驱动器这些东西,寄存器就是一段特殊的存储器,内核可以通过APB2总线对寄存器进行读写,这样就可以完成输出电平和读取电平的功能了

这个寄存器的每一位对应一个引脚,其中输出寄存器写1,对应的引脚就会输出高电平,写0,就输出低电平

输入寄存器读取为1,就证明对应的端口目前是高电平,读取为0,就是低电平

因为STM32是32位的单片机,所以STM32内部的寄存器都是32位的

但这个端口只有16位,所以这个寄存器只有低16位对应的有端口,高16位是没有用到的,这个驱动器是用来增加信号的驱动能力的

寄存器只负责存储数据,如果要进行点灯这样的操作的话,还是需要驱动器来负责增大驱动能力

GPIO位结构

保护二极管用途

首先是这个IO引脚,这里接了两个保护二极管,这个是对输入电压进行限幅的

上面这个二极管接VDD,3.3V;下面接VSS,0V

如果输入电压比3.3V还要高,那上方这个二极管就会导通

输入电压产生的电流就会直接流入VDD而不会流入内部电路

这样可以避免过高的电压对内部这些电路产生伤害

如果输入电压比0V还要低,这个电压是相对于VSS的电压,所以是可以有负电压的,那这时下方这个二极管就会导通,电流会从VSS直接流出去。而不会从内部电路汲取电流,也是可以保护内部电路的。

如果输入电压在0~3.3V之间,那两个二极管均不会导通,这时候二极管对电路没有影响,这就是保护二极管的用途。


开关

接下来电流来到开关的岔路口,这里连接了一个上拉电阻和一个下拉电阻

上拉电阻至VDD,下拉电阻至VSS,这个开关是可以通过程序进行配置的。

如果上面导通、下面断开,就是上拉输入模式

如果下面导通、上面断开,就是下拉输入模式

如果两个都断开,就是浮空输入模式

那么这个上拉下拉有什么作用呢?

这个其实就是为了给输入提供一个默认的输入电平的

因为对于一个数字的端口,输入不是高电平就是低电平

那如果输入引脚啥都不接,那到底是算高电平还是还是低电平呢?

不好说,实际情况是,如果输入啥都不接,这时输入就会处于一种浮空的状态,引脚的输入电平极易受外界干扰而改变,就像是一个物体悬浮在太空一样,它的位置是不确定的,受到一点扰动就会变化,为了避免引脚悬空导致的输入数据不确定,我们就需要在这里加上上拉或者下拉电阻了。

如果接入上拉电阻,当引脚悬空时,还有上拉电阻来保证引脚的高电平,
所以上拉输入又可以称作是默认为高电平的输入模式

下拉也是同理,就是默认为低电平的输入方式

这个上拉电阻和下拉电阻的阻值都是比较大的,是一种弱上拉和弱下拉,目的是尽量不影响正常的输入操作。


施密特触发器

电流继续前进,可以看到有一个叫做TTL肖特基触发器的东西,实际上应该是叫施密特触发器。

这个施密特触发器的作用就是对输入电压进行整形的.

它的执行逻辑是,如果输入电压大于某一阈值,输出就会瞬间升为高电平
如果输入电压小于某一阈值,输出就会瞬间降为低电平

举个例子,因为这个引脚的波形是外界输入的。虽然是数字信号,实际情况下可能会产生各种失真
如果有了施密特触发器,对于施密特触发器来说,只有高于上限或者低于下限,输出才会变化。
所以此时如果低于上限的情况,输出并不会变化,而是继续维持高电平。然后直到下次低于下限时,才会转为低电平。

这里信号即使在下限附近来回横跳,因为没有跳到上限上面去,所以输出仍然是稳定的,直到下一次高于上限,输出才会变成高,这就是施密特触发器的输出信号。

相比于输入信号,整形的信号就很完美

使用两个比较阈值来进行判断,中间留有一定的变化范围,可以有效地避免因信号波动造成的输出抖动现象

接下来经过施密特触发器整形的波形就可以直接写入输入数据寄存器了


我们再用程序读取输入数据寄存器对应某一位的数据,就可以知道端口的输入电平了

最后上面还有两路线路,这些就是连接到片上外设的一些端口

其中有模拟输入,这个是连接到ADC上的,因为ADC需要接收模拟量

另一个是复用功能输入,这个是连接到其他需要读取端口的外设上的,比如串口的输入引脚等,这根线接收的是数字量,所以在施密特触发器后面


输出部分

数字部分可以由输出数据寄存器或者片上外设控制,两种控制方式通过数据选择器接到了输出控制部分

如果选择通过输出数据寄存器进行控制,就是普通的IO口输出,写这个数据寄存器的某一位就可以操作对应的某个端口了

左边还有一个叫做位设置/清除寄存器,这个可以用来单独操作输出数据寄存器的某一位,而不影响其他位。

因为这个输出数据寄存器同时控制16个端口,并且这个寄存器只能整体读写,所以如果想单独控制其中某一个端口而不影响其他端口的话,就需要一些特殊的操作方式

第一种方式是先读出这个寄存器,然后用按位与和按位或的方式更改某一位,最后再将更改后的数据写回去,在C语言中就是&=和|=的操作,这种方法比较麻烦,效率不高,对于IO口的操作而言不太合适

第二种方式是通过设置这个位设置和位清除寄存器,如果我们要对某一位进行置1的操作,在位设置寄存器的对应位写1即可,剩下不需要操作的位写0,这样它内部就会有电路

自动将输出数据寄存器中对应位置为1,而剩下写0的位则保持不变
这样就保证了只操作其中某一位而不影响其它位,并且这是一步到位的操作

如果想对某一位进行清0的操作,就在位清除寄存器的对应位写1即可,这样内部电路就会把这位清0了,这就是第二种方式也就是这个位设置和位清除寄存器的作用

另外还有第三种操作方式,就是读写STM32中的"位带"区域,这个位带的作用就跟51单片机的位寻址作用差不多。在STM32中,专门分配的有一段地址区域,这段地址映射了RAM和外设寄存器所有的位。读写这段地址中的数据,就相当于读写所映射位置的某一位。
这就是位带的操作方式.

我们主要使用库函数来操作,库函数使用的是读写位设置和位清除寄存器的方法


接下来输出控制之后就接到了两个MOS管

上面是P-MOS,下面是N-MOS,这个MOS管就是一种电子开关。我们的信号来控制开关的导通和关闭,开关负责将IO口接到VDD或者VSS。在这里可以选择推挽、开漏或关闭三种输出方式。


推挽输出模式
在推挽输出模式下,P-MOS和N-MOS均有效。
数据寄存器为1时,上管导通,下管断开,输出直接接到VDD,就是输出高电平
数据寄存器为0时,上管断开,下管导通,输出直接接到VSS,就是输出低电平

这种模式下,高低电平均有较强的驱动能力,所以推挽输出模式也可以叫强推输出模式

在推挽输出模式下,STM32对IO口具有绝对的控制权,高低电平都由STIM32说的算


开楼模式

在开漏输出模式下,这个P-MOS是无效的,只有N-MOS在工作

数据寄存器为1时,下管断开,这时输出相当于断开,也就是高阻模式

数据寄存器为0时,下管导通,输出直接接到VSS,也就是输出低电平

这种模式下,只有低电平有驱动能力,高电平是没有驱动能力的

那这个模式有什么用呢,这个开漏模式可以作为通信协议的驱动方式

比如I2C通信的引脚,就是使用的开漏模式.在多机通信的情况下,这个模式可以避免各个设备的相互干扰.
另外开漏模式还可以用于输出5V的电平信号,比如在10口外接一个上拉电阻到5V的电源
当输出低电平时,由内部的N-MOS直接接VSS;当输出高电平时,由外部的上拉电阻拉高至5V

这样就可以输出5V的电平信号,用于兼容一些5V电平的设备,这就是开漏输出的主要用途


剩下的一种状态就是关闭,这个是当引脚配置为输入模式的时候,这两个MOS管都无效,也就是输出关闭,端口的电平由外部信号来控制。

8种工作模式

通过配置GPIO的端口配置寄存器,端口可以配置成以下8种模式

前面三个模式的电路结构基本是一样的,区别就是上拉电阻和下拉电阻的连接,它们都属于数字的输入口,那特征就是,都可以读取端口的高低电平。

当引脚悬空时,上拉输入默认是高电平,下拉输入默认是低电平。而浮空输入的电平是不确定的,所以在使用浮空输入时,端口一定要接上一个连续的驱动源,不能出现悬空的状态。


浮空/上拉/下拉输入

可以看到,在输入模式下,输出驱动器是断开的。端口只能输入而不能输出。上面两个电阻(开关)可以选择为上拉工作、下拉工作或者都不工作,前面也提及了。
对应的就是上拉输入、下拉输入和浮空输入。

然后输入通过施密特触发器进行波形整形后,连接到输入数据寄存器。另外右边这个输入保护这里,上面写的是VDD或者VDD_FT,这就是3.3V端口和容忍5V端口的区别。

最下面一行可以看到,这里说VDD_FT对5V容忍IO脚是特殊的,它与VDD不同

这个容忍5V的引脚,它的上边保护二极管要做一下处理。

要不然这里直接接VDD 3.3V的话,外部再接入5V电压就会导致上边二极管开启,并且产生比较大的电流,这个是不太妥当的


模拟输入

特征是GPIO无效,引脚直接接入内部ADC

这个模拟输入可以说是ADC模数转换器的专属配置了

我们看一下模拟输入的结构

这里输出是断开的,输入的施密特触发器也是关闭的无效状态

所以整个GPIO的左边都是没用的,就只剩下另外一根线了。也就是从引脚直接接入片上外设,也就是ADC

所以,当我们使用ADC的时候,将引脚配置为模拟输入就行了,其他时候一般用不到模拟输入。


开漏/推挽输出

开漏输出和推挽输出,这两个电路结构也基本一样,都是数字输出端口,可以用于输出高低电平

区别就是开漏输出的高电平呈现的是高阻态,没用驱动能力。

而推挽输出的高低电平都是具有驱动能力的

这时候,输出是由输出数据寄存器控制的,这个P-MOS无效就是开漏输出,如果P-MOS和N-MOS都有效,就是推挽输出

另外我们还可以看到,在输出模式下,输入模式也是有效的。但是我们刚才的电路图,在输入模式下,输出都是无效的。

这是因为一个端口只能有一个输出,但可以有多个输入。

所以当配置成输出模式的时候,内部也可以顺便输入一下,这是也是没啥影响的


复用开漏/推挽输出

复用开漏输出和复用推挽输出其实跟普通的差不多。

只不过是复用的输出,引脚电平是由片上外设控制的

看图我们可以发现,通用的输出这里是没有连接的

引脚的控制权转移到了片上外设,由片上外设来控制

在输入部分,片上外设也可以读取引脚的电平,同时普通的输入也是有效的,顺便接收一下电平信号。

其实在GPIO的这8种模式中,除了模拟输入这个模式会关闭数字的输入功能。在其他的7个模式中,所有的输入都是有效的

这些就是STM32 GPIO的全部介绍了。

官方手册

外设GPIO配置

当我们使用这些片上外设的引脚时,可以参考这个表里给的配置

GPIO配置寄存器

每一个端口的模式由4位进行配置,16个端口就需要64位,所以这里的配置寄存器有两个

一个是端口配置低寄存器,一个是端口配置高寄存器

具体怎么配置,可以看手册介绍

还多了一项GPIO输出的速度

这个GPIO的输出速度可以限制输出引脚的最大翻转速度,这个设计出来是为了低功耗和稳定性的

一般要求不高的时候一般配置成50MHz就可以了

端口输入数据寄存器

也就是这个寄存器

里面的低16位对应16个引脚,高16位没有使用

端口输出数据寄存器

也就是这个寄存器

同样,低16位对应16个引脚,高16位没有使用

端口位设置/清除寄存器

也就是这个寄存器

这个寄存器的高16位是进行位清除的,低16位是进行16位设置的

写1就是设置或者清除,写0就是不产生影响

端口位清除寄存器

这个寄存器的低16位和上面这个寄存器的高16位功能是一样的。

那为什么还要有这个寄存器呢?这个是为了方便操作设置的

如果你只想单一的进行位设置或者位清除,那位设置时,用上面这个寄存器,位清除时,用下面这个寄存器

如果相对多个端口同时进行位设置和位清除,那就使用前面的端口位设置/清除寄存器就行了。

这样可以保证位设置和位清除的同步性

当然了你要对信号的同步性要求不高的话,先位设置再位清除也是没问题的。

端口配置锁定寄存器

这个可以对端口的配置进行锁定,防止意外更改。

那有关STM32内部的GPIO外设,就讲完了。

现在再来看看STM32外部的设备和电路

LED和蜂鸣器

LED:发光二极管,正向通电点亮,反向通电不亮

如果是引脚没有剪过的LED,其中长脚是正极,短脚是负极

蜂鸣器分为有源蜂鸣器和无源蜂鸣器

有源蜂鸣器:内部自带振荡源,将正负极接上直流电压即可持续发声,频率固定

无源蜂鸣器:内部不带振荡源,需要控制器提供振荡脉冲才可发声,调整提供振荡脉冲的频率,可发出不同频率的声音

通过LED内部也可以看正负极,这里较小的一半是正极,较大的一半是负极,这就是LED

有源蜂鸣器

原理图

这里用了一个三极管开关进行驱动,我们在VCC和GND分别接上正负极的供电,然后中间这个引脚接低电平,蜂鸣器就会响,接高电平,蜂鸣器就关闭

可以看到我们这个写的是低电平触发,这就是有源蜂鸣器的用法。

LED和蜂鸣器的硬件电路

这里左边两个图是使用STM32的GPIO口驱动LED的电路,

左上是低电平驱动的电路,LED正极接3.3V,负极通过一个限流电阻接到PA0上

当PA0输出低电平时,LED两端就会产生电压差,就会形成正向导通的电流,这样LED就会点亮了

当PA0输出高电平时,因为LED两端都是3.3V的电压,不会形成电流,所以高电平LED就是熄灭。

这里的限流电阻一般都是要接的,,一方面可以防止LED因为电流过大而烧毁,另一方面它也可以调整LED的亮度

如果觉得LED太亮,可以适当地增大限流电阻的阻值。

当然了,我们目前为了简化电路,就省去了。之后自己设计可加上。

左下是

高电平驱动的电路,LED负极接GND,正极通过一个限流电阻接到PA0上,这时就是高电平点亮,低电平熄灭了。

那么这两种驱动方式如何选择呢?

这就得看这个IO口高低电平的驱动能力如何了

前面介绍了,这个GPIO在推挽输出模式下,高低电平均有比较强的驱动能力。所以在这里两种接法均可。

但是在单片机的电路里,一般倾向于使用第一种接法。因为很多单片机或者芯片,都使用了高电平弱驱动,低电平强驱动的规则。这样可以一定程度避免高低电平打架。

所以如果高电平驱动能力弱,就不能使用第二种连接方法了。

右边的蜂鸣器电路

这里使用了三极管开关的驱动方案,三极管开关是最简单的驱动电路了。对于功率稍微大一点的,直接用IO口驱动会导致STM32负担过重,这时候就可以用一个三极管驱动电路来完成驱动的任务。

右上这个图是PNP三极管的驱动电路,三极管的左边是基极,带箭头的是发射极,剩下的是集电极。它左边的基极给低电平,三极管就会导通。那通过3.3V和GND,就可以给蜂鸣器提供驱动电流了。基极给高电平,三极管截止,蜂鸣器就没有电流。

右下是NPN三极管的驱动电路
同样,左边是基极,带箭头的是发射极,剩下的是集电极。它的驱动逻辑跟上面的相反。

基极给高电平导通,低电平断开。另外注意一下,这个PNP的三极管最好接在上边,NPN的三极管最好接在下边。这是因为三极管的通断,是需要在发射极和基极直接产生一定的开启电压的

如果把负载接在发射极这边,可能会导致三极管不能开启。

PNP 最好接在上边(高端(发射极接电源))),NPN 最好接在下边(低端((发射极接地)))

原因:三极管需要在发射极和基极之间建立约 0.7V 的导通电压。
如果负载接在发射极一侧,发射极电位会被负载“抬高”(NPN 做高端)或“拉低”(PNP 做低端),导致所需的基极驱动电压超出单片机 IO 的范围,三极管就可能无法导通或无法完全饱和。

这里负载就是LED跟喇叭。

面包板

当我们把元件的引脚插到面包板的孔里后,它的内部金属爪就会夹住引脚。

我们可以发现金属爪的排列规律是,中间的金属爪是竖着放的

上下四排是连在一起的四个整体的金属爪,那就对应这个面包板的孔的连接关系。

就是在这里,竖着的5个孔内部都是连接在一起的。这样我们元件插在一纵排的不同孔位时,内部的金属爪就实现了线路的连接。

上下两边,第一排时正极,第二排是负极,第三排也是正极,第四排也是负极

如果我们需要供电,就从上下的孔位中,用跳线引出来即可

感谢你的观看,期待我们下次再见!

LED闪烁、LED流水灯、蜂鸣器

GPIO的输入

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/9 0:19:19

开发者技能图谱:如何用中继模式构建高效学习路径

1. 项目概述:一个开发者技能中继站的诞生最近在GitHub上看到一个挺有意思的项目,叫“relay-dev-skills”。光看这个名字,你可能觉得有点抽象,但点进去一看,其实就是一个开发者技能图谱的集合。说白了,它就像…

作者头像 李华
网站建设 2026/5/9 0:05:49

液压风力涡轮机:用流体传动重构风电系统架构的工程实践

1. 风力发电的“常规”与“另类”:为什么我们要重新审视机舱设计?干这行十几年,跟各种发电设备打交道,风力涡轮机算是老朋友了。大家现在看到的绝大多数风电机组,结构都差不多:高高的塔筒顶上,有…

作者头像 李华
网站建设 2026/5/8 23:39:31

角色扮演大语言模型:从核心原理到多智能体架构的实践指南

1. 角色扮演大语言模型:从概念到前沿的深度解析如果你对AI聊天机器人、虚拟角色或者让AI模拟特定人物(比如历史名人、小说角色甚至是你自己)感兴趣,那么“角色扮演大语言模型”这个领域就是你绕不开的核心。这不仅仅是让AI说几句符…

作者头像 李华
网站建设 2026/5/8 23:33:52

轻量级Python爬虫框架pocketclaw:快速构建与工程化实践指南

1. 项目概述与核心价值最近在折腾一些数据采集和自动化任务时,发现了一个挺有意思的项目,叫pocketclaw。这个名字本身就挺有画面感的,“口袋里的爪子”,一听就知道是个轻量级、便携式的爬虫工具。作为一个在数据领域摸爬滚打了十多…

作者头像 李华