【嵌入式STM32】GPIO
GPIO(General Purpose Input/Output,通用输入/输出),简单总结一下,虽然很简单=。
GPIO(General Purpose Input/Output,通用输入/输出),简单总结一下,虽然很简单=。=
1.逻辑电平与高组态
1.1 逻辑电平(Logic Level)
在数字电路中,信号通常只有两种状态:
| 状态 | 英文 | 代表电压 | 说明 |
|---|---|---|---|
| 高电平 | High (逻辑1) | STM32/ESP32等为约 3.3V | 电路中的“开”状态,表示逻辑1 |
| 低电平 | Low (逻辑0) | 0V | 电路中的“关”状态,表示逻辑0 |
- 具体电压值会根据单片机型号和供电电压不同而变化(如5V逻辑、3.3V逻辑等)。
- 高电平和低电平是数字信号的基础。
1.2 高阻态(High Impedance,Hi-Z)
- 定义:高阻态相当于引脚断开,输出端口不驱动电流,阻抗非常大,类似“断路”。
- 效果:
- 不向外输出任何信号。
- 外部电路无法通过该引脚吸收或送出电流。
- 举例:
- 电压表的两个表笔之间就处于高阻态,电压表不会影响电路。
- 三态总线(3-state bus)中的第三种状态就是高阻态。
1.3 STM32 GPIO 的三种主要状态
| GPIO 状态 | 作用说明 |
|---|---|
| 输出高电平 | 引脚输出3.3V,连接负载为高电平 |
| 输出低电平 | 引脚输出0V,连接负载为低电平 |
| 高阻态(输入) | 引脚不驱动电压,处于输入模式,外部信号决定电平 |
- 输出模式:单片机控制引脚强制输出高或低电平。
- 输入模式:引脚不主动输出,处于高阻态,等待外部信号输入。
2.最简单的实验 - 点灯
先看一下板子(nucleo_144pins官方板卡)某个灯,注意引脚接地,那么GPIO输出高电平会点亮该LED:
对应PB7。这里直接打开的是官方的mx demo文件:
这个mx配置中,灯已经提前配置好了:
注意这个User Label的名字直接对应到程序中是可以找到宏定义的:
让它闪烁起来吧:
void StartDefaultTask(void *argument)
{
/* Infinite loop */
for(;;)
{
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
osDelay(1000);
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_RESET);
osDelay(1000);
}
}
3.GPIO配置
首先GPIO可配置为三种方式:GPIO_Input、GPIO_Output和GPIO_Analog,如下图:
区分:
还有一个GPIO_EXTIx,GPIO_EXTI 即 GPIO External Interrupt,是指通过GPIO引脚触发的外部中断。
它允许单片机在检测到某个GPIO引脚上的电平变化(上升沿、下降沿或双边沿)时,立即响应并进入中断服务程序。
3.1 GPIO_Input 输入
随便选一个端口,配置成输入模式:
- Pull-Up(上拉):通过内部电阻将引脚电平“拉高”到逻辑高电平(3.3V),防止引脚悬空(浮空)导致电平不稳定。
- Pull-Down(下拉):通过内部电阻将引脚电平“拉低”到逻辑低电平(0V),同样防止悬空。
- No Pull(无上下拉):不使用任何内部电阻,电平由外部电路决定。
在GPIO_Input模式中,当外部没有主动驱动信号时(比如开关断开、悬空),上拉/下拉电阻能保证输入端口有确定的电平,避免噪声和误触发。
防止“浮空”状态引起的随机电平跳变和不稳定输入。例如,按键未按下时,输入引脚没有外部信号,内置上拉使引脚保持“高”电平。按键输入常用 Pull-Up(按下时引脚接地,未按时内部上拉保持高电平)。 有些传感器或信号线可能用 Pull-Down。
【内置上下拉电阻的问题】
内置上下拉电阻的阻值
在 STM32 中,内置上下拉电阻的阻值一般为 30∼50kΩ(部分提供给 USB 使用的引脚会内置较小的上拉电阻,请参考芯片数据手册),阻值较大,因此不会出现上拉电阻阻值过小导致的问题。但是,阻值较大,因此会导致上升时间过长。比如,内置上拉电阻通常不适合用于 I2C 总线。
3.2 GPIO_Output 输出
来看一下MX中可配置的项:
代码调用:
HAL_GPIO_WritePin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
GPIO_PinState state = HAL_GPIO_ReadPin(LD2_GPIO_Port, LD2_Pin, GPIO_PIN_SET);
HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin); //翻转电平
3.2.1 GPIO output level (GPIO输出电平)
配置GPIO引脚初始化后的默认输出电平。
- Low:初始化时输出低电平(0V,逻辑0)。
- High:初始化时输出高电平(3.3V,逻辑1)。
【注意】
只有当GPIO工作在输出模式(如推挽输出)时,此设置才生效。
该设置决定芯片上电或复位后,GPIO引脚的初始状态。
3.2.2 GPIO mode
定义GPIO引脚的工作模式。
-
推挽输出
当配置为推挽输出(Push-pull Output)时,单片机可以输出「低电平」(GPIO_PIN_RESET)或「高电平」(GPIO_PIN_SET)。 -
开漏输出
当配置为开漏输出(Open-drain Output)时,单片机可以输出「低电平」(GPIO_PIN_RESET)或「高阻态」(GPIO_PIN_SET),高阻态下,相当于断开,所以外部电路无法通过该引脚吸收或送出电流。
3.2.3 GPIO Pull-up/Pull-down
在输出模式下,该选项一般无作用,设置为下面即可:
3.2.4 Max output speed “变化速率”
指 GPIO 引脚输出电平变化时的上升沿和下降沿的陡峭程度,即信号切换的“速度”或“带宽”。
这里的“速度”不是指时钟频率,而是指输出信号在物理线上电压变化的快慢(上升时间和下降时间)。
3.2.5 读取GPIO状态
在输出模式下,我们仍然可以读取到 GPIO 的外部真实状态为高电平还是低电平,这在开漏模式下尤为有用。
在开漏模式下,如果输出「高阻态」(GPIO_PIN_SET),那么相当于单片机对外部电路没有影响,此时外部电路的电平由外部电路自身决定,而我们可以通过读取 GPIO 的状态来判断外部电路的真实电平状态。
3.3 GPIO EXTI
当 GPIO 引脚的电平发生变化时,CPU 可以通过中断或者事件的方式来感知到这个变化。
中断方式可以进入中断函数,
但事件方式不触发中断,不会进入中断函数,它是直接硬件触发的,响应速度快且不打断CPU执行。
3.3.1 MX配置

| 选项 | 类型 | 触发边沿 | 触发机制 | 典型用途 |
|---|---|---|---|---|
| External Interrupt Mode with Rising edge … | 外部中断 | 上升沿 | 触发中断,执行ISR | 按键抬起检测、信号开始 |
| External Interrupt Mode with Falling edge … | 外部中断 | 下降沿 | 触发中断,执行ISR | 按键按下检测、信号结束 |
| External Interrupt Mode with Rising/Falling … | 外部中断 | 上升沿和下降沿 | 触发中断,执行ISR | 捕获所有边沿,计数脉冲 |
| External Event Mode with Rising edge … | 外部事件 | 上升沿 | 触发事件,不中断CPU | 定时器捕获、DMA触发 |
| External Event Mode with Falling edge … | 外部事件 | 下降沿 | 触发事件,不中断CPU | 定时器捕获、DMA触发 |
| External Event Mode with Rising/Falling … | 外部事件 | 上升沿和下降沿 | 触发事件,不中断CPU | 对信号边沿的非中断响应 |
5.实验1 - 外部中断 - 按键点灯
找一个按键做实验,按下后控制LD3的翻转,下面是USER按键,该按键是有消抖电路的,接入PC13端口,按下时,控制上面LED翻转:
LD3:
1、GPIO配置:
2、配置为上升沿触发中断,同时下拉为低电平,这样可以保证第一次按下有电平跳转:
3、使能中断:
4、代码,GPIO配置、中断配置MX已经自动创建完毕,我们新建一个 HAL_GPIO_EXTI_Callback 函数即可:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if (GPIO_Pin == USER_Btn_Pin)
{
HAL_GPIO_TogglePin(LD3_GPIO_Port, LD3_Pin);
}
}
5.实验2 - 外部事件 - 按键启动定时器
发现这个按键对应的引脚,竟然不支持Timx_CH1捕获或者TIMx_ETR方式,这样就没法做这个实验了。
更多推荐



所有评论(0)