Hello,大家好。接下来我会更新一篇合集,把常见的stm32的外设配置,以及实际工程中自己遇到的问题分享在这一篇合集之中,希望能对大家有所帮助。
1.GPIO基础概念
GPIO(General-Purpose Input/Output)即通用输入输出端口,是嵌入式系统和微控制器中用于与外部设备交互的接口。它可以通过软件配置为输入或输出模式,实现数字信号的读取或驱动。
主要特性
-
双向性:可配置为输入(读取外部信号)或输出(驱动外部设备)。
-
数字信号:仅处理高电平(通常为1/3.3V/5V)或低电平(0V)。
-
无专用协议:直接通过电平变化传输数据,需自行定义通信逻辑。
工作模式
输入模式
用于读取外部信号状态,常见子模式:
-
浮空输入(无上下拉电阻,易受干扰)。
-
上拉/下拉输入(内置电阻稳定默认电平)。
输出模式
用于控制外部设备,常见子模式:
-
推挽输出(可驱动高低电平,常用模式)。
-
开漏输出(仅可拉低电平,需外接上拉电阻)
典型应用场景
-
控制LED、继电器等简单外设。
-
读取按键、开关状态。
-
模拟I2C、SPI等协议(需软件实现时序)。
单片机内部的io结构如下图所示:

每一个单片机的io都被分为了两部分,一个是输入一个是输出。
下面我们来看看具体的代码参数配置。
// 设置PA5为推挽输出
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Pin = GPIO_PIN_5;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
以上代码是对最基础的io功能做了配置,将PA5设置为输出模式的推挽输出。
看到这里可能很多入门者会对不同的io状态存在疑惑,我来详细解答以下各个io模式下的区别:
一、输入模式
输入模式用于读取外部信号的状态(高电平或低电平)。STM32 提供 4 种输入配置:
-
浮空输入
-
原理: 内部既不接上拉电阻也不接下拉电阻。引脚完全“悬空”,电平状态完全由外部电路决定。
-
区别: 电平状态最易受外部噪声干扰。如果外部断开或处于高阻态,引脚电平不确定。
-
应用:
-
连接外部已经自带确定上拉或下拉的器件(如 I2C 总线上的上拉电阻)。
-
连接开漏输出的设备(如 I2C 的 SDA/SCL)。
-
不推荐用于按键等直接连接,因为悬空时电平不确定会导致误触发。
-
-
配置代码示例 (HAL库):
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL;
-
-
上拉输入
-
原理: 内部通过一个电阻(通常几十千欧)连接到 VDD (电源电压)。当外部没有驱动或驱动为高阻态时,引脚被拉至高电平。
-
区别: 内置上拉电阻,默认高电平。外部低电平信号需要能“战胜”这个上拉电阻才能将引脚拉低。
-
应用:
-
按键检测: 按键一端接地,另一端接GPIO。按键未按下时,上拉使GPIO为高;按键按下时,GPIO被直接拉到地变为低。
-
需要默认高电平状态,且外部驱动能力较弱时。
-
-
配置代码示例:
GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_PULLUP;
-
-
下拉输入
-
原理: 内部通过一个电阻(通常几十千欧)连接到 VSS (地)。当外部没有驱动或驱动为高阻态时,引脚被拉至低电平。
-
区别: 内置下拉电阻,默认低电平。外部高电平信号需要能“战胜”这个下拉电阻才能将引脚拉高。
-
应用:
-
按键检测(反逻辑): 按键一端接VDD,另一端接GPIO。按键未按下时,下拉使GPIO为低;按键按下时,GPIO被直接拉到VDD变为高。
-
需要默认低电平状态,且外部驱动能力较弱时。
-
-
-
模拟输入
-
原理: 信号直接连接到内部的 ADC(模数转换器)或 DAC(数模转换器,如果支持)模块。关闭了施密特触发器、上拉/下拉电阻和输出驱动器。目的是让外部模拟电压尽可能无失真地进入ADC。
-
区别: 不能用作数字输入(读取 IDR 寄存器无意义)。引脚呈现高阻态。仅用于 ADC 采样或 DAC 输出(当配置为模拟模式时,DAC 输出自动使能,无需配置为输出模式)。
-
应用:
-
连接传感器输出(如温度传感器、光敏电阻分压、麦克风前置放大输出等)进行 ADC 采样。
-
使用 DAC 输出模拟电压(此时引脚是输出模拟信号)。
-
-
配置代码示例:
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;(上拉/下拉配置在此模式下无效)
-
输入模式关键点总结:
-
浮空、上拉、下拉用于数字信号输入。
-
模拟输入用于模拟信号输入(或 DAC 输出)。
-
上拉/下拉电阻提供默认状态并增强抗噪能力,特别适合按键等应用。
-
施密特触发器存在于所有数字输入模式(模拟模式除外),用于整形输入波形,提高抗噪性并产生干净的逻辑电平。
二、输出模式
输出模式用于驱动外部负载或向其他器件发送信号。STM32 提供 2 种主要的输出驱动器结构,每种又可以配置不同的速度:
-
开漏输出
-
原理:
-
内部只有 N-MOS 管连接到地。
-
当输出逻辑
0时,N-MOS 导通,引脚被强下拉到地。 -
当输出逻辑
1时,N-MOS 关断,引脚既不拉高也不拉低(高阻态)。需要外部上拉电阻才能将引脚拉到高电平(通常是 VDD 或另一个电压)。
-
-
特点/区别:
-
不能主动输出高电平。 高电平依赖外部上拉。
-
具有“线与”特性:多个开漏输出连接到同一总线时,只要有一个输出
0,总线就是0;只有所有都输出1(高阻态),总线才被外部上拉拉成1。这是 I2C、SMBus 等总线的基础。 -
可以方便地实现电平转换:外部上拉电阻可以接到一个比芯片 VDD 更高的电压(前提是引脚本身支持该电压,如 5V-tolerant 引脚)。例如,STM32 (3.3V) 可以通过开漏输出+外部 5V 上拉与 5V 器件通信。
-
驱动能力(拉低电流)由芯片决定。
-
-
应用:
-
I2C (SDA, SCL) 总线: 利用线与特性进行多主仲裁。
-
需要电平转换的场合(驱动 5V 逻辑器件)。
-
驱动电流较大的器件(如 LED),但高电平仍需外部上拉(可能结合其他电路)。
-
需要线与逻辑的应用。
-
-
配置代码示例:
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; GPIO_InitStruct.Pull = GPIO_NOPULL;(外部上拉是必须的!) 或GPIO_PULLUP(如果内部上拉足够强且电压合适,但通常建议用外部电阻)。
-
-
推挽输出
-
原理:
-
内部包含一个 P-MOS 管连接到 VDD 和一个 N-MOS 管连接到 VSS。
-
当输出逻辑
0时,P-MOS 关断,N-MOS 导通,引脚被强下拉到地。 -
当输出逻辑
1时,P-MOS 导通,N-MOS 关断,引脚被强上拉到 VDD。
-
-
特点/区别:
-
能主动输出强高电平和强低电平,驱动能力强。
-
高低电平切换速度快。
-
输出阻抗低(在高低电平时)。
-
不具备线与特性。直接将两个推挽输出短接并试图驱动不同电平会导致短路(大电流),可能损坏芯片!
-
-
下面讲一讲如何使用cubemx来对io口进行基础的配置:

GPIO output level是引脚的初始化电平,这在按键的应用中会经常出现,此时的io需要上下拉电阻配合以初始化一个确定的电平,使用按键时一定不能配置成浮空状态!
GPIO mode时配置上文讲到的几种io的模式,不太了解的读者可以往上翻一翻原文。
下面的就是输出模式下的上下拉,以及io的速度相关的配置,我实测的话,low speed下io的反转速度可以达到500kHz的样子或者更高,大家有兴趣可以自己试着用示波器打一下。
好了,这篇文章就写到这里,希望对你有所帮助!
1万+






