GPIO笔记

GPIO端口位的基本结构

image

image

我们通过寄存器向GPIO写0或1时不能直接给输出数据寄存器,而是要写位设置清除寄存器,而且位设置清除寄存器的每两位对应的一个输出数据寄存器(详见参考手册),0到15为1且16到31为0就输出1,到15为0且16到31为1就输出0,如果都为1那么0到15有高优先级。

IO的八种工作模式

输出模式

通用输出推挽

通用输出开漏

复用输出推挽

复用输出开漏

输出控制

image

这个输出控制是反相器,当向GPIO写1经过输出控制就会变成0,当向GPIO写0经过输出控制就会变成1。

推挽和开漏

image

推挽就是这一对MOS管交替导通(写1:N-MOS导通,写0:P-MOS导通)。

如果向GPIO引脚写0,输出控制反向输出1,P-MOS关断,N-MOS导通,GPIO输出低电平。

如果向GPIO引脚写1,输出控制反向输出1,P-MOS导通,N-MOS关断,GPIO输出高电平。

开漏是上边的P-MOS管是一直断开的。

如果向GPIO引脚写0,P-MOS关断,N-MOS导通,GPIO输出低电平。

如果向GPIO引脚写1,P-MOS关断,N-MOS关断,GPIO悬空,不产生电流,也叫高阻抗。

通用和复用

通用是通过程序直接控制IO引脚输出高低电压。

复用是通过芯片的其他模块控制IO引脚输出高低电压。

使用场景

通用推挽输出:这个模式的特点是驱动能力强,电平稳定,所以经常用在驱动LED,蜂鸣器普通IO输出。

通用开漏输出:这个模式的特点是可与多设备共享线,实现线与,所以经常用在I²C,1-Wire、开集模式通信、外设共享信号。

复用输出推挽:这个模式的特点是高速输出,驱动强,所以经常用在SPI、USART TX、PWM、电机控制、定时器输出。

复用输出开漏:这个模式的特点是可以进行电平兼容,所以经常用在I²C SCL/SDA、CAN(部分情况)。

image

输入模式

输入上拉

输入下拉

输入浮空

模拟输入:这个是用来接入模拟信号

image

输入上拉,输入下拉,输入浮空都是和上图中的电阻有关。其中上面的电阻叫做上拉电阻,下面的电阻叫做下拉电阻,两个电阻旁边各有一个开关,上拉电阻连接到高电压Vdd下拉电阻连接到低电压Vss。

输入上拉:这个模式就是闭合了上面的开关,使能了上拉电阻。

输入下拉:这个模式就是闭合了下面的开关,使能了下拉电阻。

输入浮空:这个模式就是两个电阻都不闭合,既不使能上拉电阻也不使能下拉电阻。当外部接了一个上拉电阻或下拉电阻就可以配置为浮空模式。

作用:当IO引脚工作在输入模式下的时候,IO引脚的作用就是去测量外部输入信息的电压,就相当一块电压表,因此它的内阻应无穷大,如果没有上拉电阻和下拉电阻这个地方的就会接收到空间中的电磁波,就读到了随机的0和1。所以上拉电阻的作用就是当引脚悬空时,提供默认的高电平,也就是避免出现悬空导致信号不确定,下拉电阻同理。

image

GPIO闪烁LED

(HAL+CubeMx)

image

GPIO output level:用来设置IO引脚的初始值

Low表示初值为0

High表示初值为1

GPIO mode:用来选择IO引脚的模式。

output push-pull代表输出推挽

output open-drain代表输出开漏

GPIO Pull-up/Pull-down:用来选择上拉电阻和下拉电阻

No pull-up and no pull-down:代表既不上拉也不下拉

Pull-up:代表上拉

Pull-down:代表下拉

Maximum output speed:用来设置引脚的最大输出速度

low表示低速(2M)

Medium表示中速(10M)

High表示高速(50M)

User Label:用来设置用户自定义标签

下图是设置完成的结果

image

库函数

void HAL_GPIO_WritePin(GPIOx,GPIO_Pin,PinState)

这个函数的作用是向GPIO写0或者写1。

参数GPIOx用来填写引脚的组编号,x可以取A...D。

参数GPIO_Pin用来设置引脚编号,可以取GPIO_PIN_0...15。

参数PinState用来指定向IO写0还是写1,可以填写GPIO_PIN_RESET代表0,GPIO_PIN_SET代表1。

void HAL_Delay(uint32_t Delay)

作用:延迟一段时间

参数Delay:要延迟的时间长度,单位ms

代码

image

(纯HAL)

库函数

___HAL_RCC_GPIOx_CLK_ENABLE()

这个函数的作用是使能特定GPIO端口的时钟。

参数GPIOx:这里可以写A,B,C...

HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)

这个函数的作用是初始化GPIO的。

参数GPIO_TypeDef *GPIOx:这个参数是传入初始化的引脚的组编号,例如GPIOA,GPIOB......

参数GPIO_InitTypeDef *GPIO_Init:这个参数是配置GPIO具体参数的,是一个结构体,结构体中的成员如下:

Pin:设置引脚编号。

Mode:设置GPIO模式。

Pull:设置是否有上拉电阻和下拉电阻。

Speed:设置GPIO速度。

代码

GPIO按钮点亮LED

(HAL+CubeMx)

image

当我们松开按钮时,IO引脚悬空,此时在上拉电阻的作用下,我们读取到的电平就是高电平。

当我们按下按钮时,IO引脚就接地,我们读取到的电平就是低电平。

image-20251128152832828

GPIO mode:用来选择IO引脚的模式。

在输入模式下只有一种选择。

GPIO Pull-up/Pull-down

No pull-up and no pull-down:代表既不上拉也不下拉也就是输入浮空

Pull-up:代表上拉

Pull-down:代表下拉

User Label:用来设置用户自定义标签

下面是设置完成的结果

image

库函数

GPIO_PinState HAL_GPIO_ReadPin(GPIOx,GPIO_Pin)

作用:读取IO的当前值

参数GPIOx:组编号,x取A...D

参数GPIO_Pin:引脚编号,GPIO_PIN_0...15

返回值:IO引脚的读数,GPIO_PIN_RESET - 0 GPIO_PIN_SET - 1

注意

因为机械按键在按下的时候会有抖动所以在代码中要延时大概10毫秒再检测按键是否按下,这样就可以避免按键抖动。

image

代码

image

初始化GPIO模版

#include "stm32xxxx.h" // 根据您的具体芯片型号更改
#include "xxx.h"      // 通常包含一些宏定义
// 定义一个初始化函数
void MX_GPIO_Init(void)//哪个外设需要就将MX改为什么,例如LED_GPIO_Init
{
    // 1. 定义 GPIO 结构体变量
    GPIO_InitTypeDef GPIO_InitStruct = {0};
 /*==========================================================
 * 步骤一:使能 GPIO 端口时钟
 * - 必须在操作任何 GPIO 寄存器之前执行!
 * ==========================================================
 */
	// 示例:如果您需要使用 GPIOC 和 GPIOA
	__HAL_RCC_GPIOC_CLK_ENABLE();
	__HAL_RCC_GPIOA_CLK_ENABLE();

	// 如果您使用的是其他端口,请对应开启
	// __HAL_RCC_GPIOB_CLK_ENABLE();
	// __HAL_RCC_GPIOD_CLK_ENABLE(); 
	
 /*==========================================================
 * 步骤二:配置具体的 GPIO 引脚 (例如,配置 LED 所在的 PC13)
 * ==========================================================
 */
	// 1. 选择要配置的引脚
	GPIO_InitStruct.Pin = GPIO_PIN_13; 

	// 2. 配置模式:设置为推挽输出模式
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 

	// 3. 配置上下拉:设置为无上拉/下拉 (输出模式常用)
	GPIO_InitStruct.Pull = GPIO_NOPULL; 

	// 4. 配置速度:设置为低速 (普通 LED/按键即可,高速用于 SPI/I2C 等)
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 

	// 5. 调用初始化函数,将配置应用到 GPIOC 端口
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
}
// ==========================================================
// 在 main 函数中调用
// int main(void)
// {
//     HAL_Init(); 
//     MX_GPIO_Init();
//     while (1)
//     {
//         // ... 循环逻辑
//     }
// }
posted @ 2026-01-24 21:24  wind_one  阅读(4)  评论(0)    收藏  举报